From 8afe40c185ec2e1c435137f9e5ff1857a9fdba3f Mon Sep 17 00:00:00 2001 From: Matt Swain Date: Mon, 15 May 2023 17:38:19 +1000 Subject: [PATCH 01/17] Added unit tests --- .../Behaviors/SelectionBoxBehaviour.cs | 23 ++++ src/Blazor.Diagrams.Core/Diagram.cs | 13 +- .../Options/DiagramBehaviourOptions.cs | 41 ++++++ .../Options/DiagramOptions.cs | 1 + .../Behaviors/PanBehaviourTests.cs | 52 +++++++ .../Behaviors/ScrollBehaviourTests.cs | 40 ++++++ .../Behaviors/SelectionBoxBehaviourTests.cs | 129 ++++++++++++++++++ .../Behaviors/ZoomBehaviourTests.cs | 41 ++++++ .../Options/DiagramBehaviourOptionsTests.cs | 102 ++++++++++++++ .../Widgets/SelectionBoxWidgetTests.cs | 52 +++++++ 10 files changed, 493 insertions(+), 1 deletion(-) create mode 100644 src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehaviour.cs create mode 100644 src/Blazor.Diagrams.Core/Options/DiagramBehaviourOptions.cs create mode 100644 tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviourTests.cs create mode 100644 tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviourTests.cs create mode 100644 tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviourTests.cs create mode 100644 tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviourTests.cs create mode 100644 tests/Blazor.Diagrams.Core.Tests/Options/DiagramBehaviourOptionsTests.cs create mode 100644 tests/Blazor.Diagrams.Tests/Components/Widgets/SelectionBoxWidgetTests.cs diff --git a/src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehaviour.cs b/src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehaviour.cs new file mode 100644 index 000000000..d4fbca578 --- /dev/null +++ b/src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehaviour.cs @@ -0,0 +1,23 @@ +using Blazor.Diagrams.Core.Geometry; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Blazor.Diagrams.Core.Behaviors +{ + public class SelectionBoxBehavior : Behavior + { + public SelectionBoxBehavior(Diagram diagram) + : base(diagram) + { + } + + public event EventHandler BoundsChanged; + + public override void Dispose() + { + } + } +} diff --git a/src/Blazor.Diagrams.Core/Diagram.cs b/src/Blazor.Diagrams.Core/Diagram.cs index a2fffeacb..9b676aced 100644 --- a/src/Blazor.Diagrams.Core/Diagram.cs +++ b/src/Blazor.Diagrams.Core/Diagram.cs @@ -402,5 +402,16 @@ private void OnModelOrderChanged(Model model) public void TriggerPointerDoubleClick(Model? model, PointerEventArgs e) => PointerDoubleClick?.Invoke(model, e); - #endregion + #endregion + + public virtual bool IsBehaviorEnabled(PointerEventArgs e, DiagramDragBehavior Behavior) + { + return false; + } + + public virtual bool IsBehaviorEnabled(WheelEventArgs e, DiagramWheelBehavior Behavior) + { + return false; + } + } } \ No newline at end of file diff --git a/src/Blazor.Diagrams.Core/Options/DiagramBehaviourOptions.cs b/src/Blazor.Diagrams.Core/Options/DiagramBehaviourOptions.cs new file mode 100644 index 000000000..027631e6b --- /dev/null +++ b/src/Blazor.Diagrams.Core/Options/DiagramBehaviourOptions.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Blazor.Diagrams.Core.Options +{ + public class DiagramBehaviorOptions + { + public DiagramWheelBehavior DiagramWheelBehavior { get; set; } = DiagramWheelBehavior.Zoom; + + public DiagramWheelBehavior DiagramAltWheelBehavior { get; set; } = DiagramWheelBehavior.Zoom; + + public DiagramWheelBehavior DiagramCtrlWheelBehavior { get; set; } = DiagramWheelBehavior.Zoom; + + public DiagramWheelBehavior DiagramShiftWheelBehavior { get; set; } = DiagramWheelBehavior.Zoom; + + public DiagramDragBehavior DiagramDragBehavior { get; set; } = DiagramDragBehavior.Pan; + + public DiagramDragBehavior DiagramAltDragBehavior { get; set; } = DiagramDragBehavior.Pan; + + public DiagramDragBehavior DiagramCtrlDragBehavior { get; set; } = DiagramDragBehavior.Pan; + + public DiagramDragBehavior DiagramShiftDragBehavior { get; set; } = DiagramDragBehavior.Select; + } + + public enum DiagramWheelBehavior + { + None, + Zoom, + Scroll, + } + + public enum DiagramDragBehavior + { + None, + Pan, + Select, + } +} diff --git a/src/Blazor.Diagrams.Core/Options/DiagramOptions.cs b/src/Blazor.Diagrams.Core/Options/DiagramOptions.cs index 4175eda0e..b99331836 100644 --- a/src/Blazor.Diagrams.Core/Options/DiagramOptions.cs +++ b/src/Blazor.Diagrams.Core/Options/DiagramOptions.cs @@ -12,4 +12,5 @@ public class DiagramOptions public virtual DiagramGroupOptions Groups { get; } = new(); public virtual DiagramConstraintsOptions Constraints { get; } = new(); public virtual DiagramVirtualizationOptions Virtualization { get; } = new(); + public virtual DiagramBehaviorOptions Behaviors { get; init; } = new(); } \ No newline at end of file diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviourTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviourTests.cs new file mode 100644 index 000000000..f0c04c255 --- /dev/null +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviourTests.cs @@ -0,0 +1,52 @@ +using Blazor.Diagrams.Core.Events; +using Blazor.Diagrams.Core.Options; +using Moq; +using Xunit; + +namespace Blazor.Diagrams.Core.Tests.Behaviors +{ + public class PanBehaviorTests + { + [Fact] + public void Behavior_WhenBehaviorEnabled_ShouldPan() + { + // Arrange + var diagram = new Mock(null) { CallBase = true }; + diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns(true); + + Assert.Equal(0, diagram.Object.Pan.X); + Assert.Equal(0, diagram.Object.Pan.Y); + + // Act + diagram.Object.TriggerPointerDown(null, + new PointerEventArgs(100, 100, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); + diagram.Object.TriggerPointerMove(null, + new PointerEventArgs(200, 200, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); + + // Assert + Assert.Equal(100, diagram.Object.Pan.X); + Assert.Equal(100, diagram.Object.Pan.Y); + } + + [Fact] + public void Behavior_WhenBehaviorDisabled_ShouldNotPan() + { + // Arrange + var diagram = new Mock(null) { CallBase = true }; + diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns(false); + + Assert.Equal(0, diagram.Object.Pan.X); + Assert.Equal(0, diagram.Object.Pan.Y); + + // Act + diagram.Object.TriggerPointerDown(null, + new PointerEventArgs(100, 100, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); + diagram.Object.TriggerPointerMove(null, + new PointerEventArgs(200, 200, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); + + // Assert + Assert.Equal(0, diagram.Object.Pan.X); + Assert.Equal(0, diagram.Object.Pan.Y); + } + } +} diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviourTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviourTests.cs new file mode 100644 index 000000000..7f0d35c0e --- /dev/null +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviourTests.cs @@ -0,0 +1,40 @@ +using Blazor.Diagrams.Core.Events; +using Blazor.Diagrams.Core.Options; +using Moq; +using Xunit; + +namespace Blazor.Diagrams.Core.Tests.Behaviors +{ + public class ScrollBehaviorTests + { + [Fact] + public void Behavior_WhenBehaviorEnabled_ShouldScroll() + { + // Arrange + var diagram = new Mock(null) { CallBase = true }; + diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns(true); + + // Act + diagram.Object.TriggerWheel(new WheelEventArgs(100, 100, 0, 0, false, false, false, 100, 200, 0, 0)); + + // Assert + Assert.Equal(100, diagram.Object.Pan.X); + Assert.Equal(200, diagram.Object.Pan.Y); + } + + [Fact] + public void Behavior_WhenBehaviorDisabled_ShouldNotScroll() + { + // Arrange + var diagram = new Mock(null) { CallBase = true }; + diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns(false); + + // Act + diagram.Object.TriggerWheel(new WheelEventArgs(100, 100, 0, 0, false, false, false, 100, 200, 0, 0)); + + // Assert + Assert.Equal(0, diagram.Object.Pan.X); + Assert.Equal(0, diagram.Object.Pan.Y); + } + } +} diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviourTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviourTests.cs new file mode 100644 index 000000000..9ddd36e98 --- /dev/null +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviourTests.cs @@ -0,0 +1,129 @@ +using Blazor.Diagrams.Core.Behaviors; +using Blazor.Diagrams.Core.Events; +using Blazor.Diagrams.Core.Geometry; +using Blazor.Diagrams.Core.Models; +using Blazor.Diagrams.Core.Options; +using Moq; +using Xunit; + +namespace Blazor.Diagrams.Core.Tests.Behaviors +{ + public class SelectionBoxBehaviorTests + { + [Fact] + public void Behavior_WhenBehaviorEnabled_ShouldUpdateSelectionBounds() + { + // Arrange + var diagram = new Mock(null) { CallBase = true }; + diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns(true); + + var selectionBoxBehavior = diagram.Object.GetBehavior()!; + bool boundsChangedEventInvoked = false; + Rectangle? lastBounds = null; + selectionBoxBehavior.BoundsChanged += (_, newBounds) => + { + boundsChangedEventInvoked = true; + lastBounds = newBounds; + }; + + // Act + diagram.Object.TriggerPointerDown(null, + new PointerEventArgs(100, 100, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); + diagram.Object.TriggerPointerMove(null, + new PointerEventArgs(200, 150, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); + + // Assert + Assert.True(boundsChangedEventInvoked); + Assert.Equal(100, lastBounds!.Width); + Assert.Equal(50, lastBounds.Height); + Assert.Equal(100, lastBounds.Top); + Assert.Equal(100, lastBounds.Left); + } + + [Fact] + public void Behavior_WhenBehaviorDisabled_ShouldNotUpdateSelectionBounds() + { + // Arrange + var diagram = new Mock(null) { CallBase = true }; + diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns(false); + + var selectionBoxBehavior = diagram.Object.GetBehavior()!; + bool boundsChangedEventInvoked = false; + Rectangle? lastBounds = null; + selectionBoxBehavior.BoundsChanged += (_, newBounds) => + { + boundsChangedEventInvoked = true; + lastBounds = newBounds; + }; + + // Act + diagram.Object.TriggerPointerDown(null, + new PointerEventArgs(100, 100, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); + diagram.Object.TriggerPointerMove(null, + new PointerEventArgs(200, 150, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); + + // Assert + Assert.False(boundsChangedEventInvoked); + Assert.Null(lastBounds); + } + + [Fact] + public void Behavior_WithBoundsChangedDelegate_ShouldSelectNodesInsideArea() + { + // Arrange + var diagram = new Mock(null) { CallBase = true }; + diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns(true); + + var selectionBoxBehavior = diagram.Object.GetBehavior()!; + selectionBoxBehavior.BoundsChanged += (_, _) => { }; + + var node = new NodeModel() + { + Size = new Size(100, 100), + Position = new Point(150, 150) + }; + diagram.Object.Nodes.Add(node); + + // Act + diagram.Object.TriggerPointerDown(null, + new PointerEventArgs(100, 100, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); + diagram.Object.TriggerPointerMove(null, + new PointerEventArgs(300, 300, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); + + // Assert + Assert.True(node.Selected); + + diagram.Object.TriggerPointerMove(null, + 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_ShouldNotSelectNodesInsideArea() + { + // Arrange + var diagram = new Mock(null) { CallBase = true }; + diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns(true); + + var node = new NodeModel() + { + Size = new Size(100, 100), + Position = new Point(150, 150) + }; + diagram.Object.Nodes.Add(node); + + // Act + diagram.Object.TriggerPointerDown(null, + new PointerEventArgs(100, 100, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); + diagram.Object.TriggerPointerMove(null, + new PointerEventArgs(300, 300, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); + + // Assert + Assert.False(node.Selected); + + diagram.Object.TriggerPointerMove(null, + new PointerEventArgs(100, 100, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); + Assert.False(node.Selected); + } + } +} diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviourTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviourTests.cs new file mode 100644 index 000000000..26d58dcb4 --- /dev/null +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviourTests.cs @@ -0,0 +1,41 @@ +using Blazor.Diagrams.Core.Events; +using Blazor.Diagrams.Core.Geometry; +using Blazor.Diagrams.Core.Options; +using Moq; +using Xunit; + +namespace Blazor.Diagrams.Core.Tests.Behaviors +{ + public class ZoomBehaviorTests + { + [Fact] + public void Behavior_WhenBehaviorEnabled_ShouldZoom() + { + // Arrange + var diagram = new Mock(null) { CallBase = true }; + diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns(true); + diagram.Object.SetContainer(new Rectangle(0, 0, 100, 100)); + + // Act + diagram.Object.TriggerWheel(new WheelEventArgs(100, 100, 0, 0, false, false, false, 0, 100, 0, 0)); + + // Assert + Assert.Equal(1.05, diagram.Object.Zoom); + } + + [Fact] + public void Behavior_WhenBehaviorDisabled_ShouldNotZoom() + { + // Arrange + var diagram = new Mock(null) { CallBase = true }; + diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns(false); + diagram.Object.SetContainer(new Rectangle(0, 0, 100, 100)); + + // Act + diagram.Object.TriggerWheel(new WheelEventArgs(100, 100, 0, 0, false, false, false, 0, 100, 0, 0)); + + // Assert + Assert.Equal(1, diagram.Object.Zoom); + } + } +} diff --git a/tests/Blazor.Diagrams.Core.Tests/Options/DiagramBehaviourOptionsTests.cs b/tests/Blazor.Diagrams.Core.Tests/Options/DiagramBehaviourOptionsTests.cs new file mode 100644 index 000000000..de1d30cb9 --- /dev/null +++ b/tests/Blazor.Diagrams.Core.Tests/Options/DiagramBehaviourOptionsTests.cs @@ -0,0 +1,102 @@ +using Blazor.Diagrams.Core.Events; +using Blazor.Diagrams.Core.Options; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace Blazor.Diagrams.Core.Tests.Options +{ + public class DiagramBehaviourOptionsTests + { + [Fact] + public void DiagramBehaviorOptions_DragBehavior_IsEnabled() + { + var diagram = new TestDiagram(); + diagram.Options.Behaviors.DiagramDragBehavior = DiagramDragBehavior.None; + Assert.False(diagram.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true), DiagramDragBehavior.Pan)); + + diagram.Options.Behaviors.DiagramDragBehavior = DiagramDragBehavior.Pan; + Assert.True(diagram.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true), DiagramDragBehavior.Pan)); + } + + [Fact] + public void DiagramBehaviorOptions_AltDragBehavior_IsEnabled() + { + var diagram = new TestDiagram(); + diagram.Options.Behaviors.DiagramAltDragBehavior = DiagramDragBehavior.None; + Assert.False(diagram.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, false, true, 0, 0, 0, 0, 0, 0, string.Empty, true), DiagramDragBehavior.Pan)); + + diagram.Options.Behaviors.DiagramAltDragBehavior = DiagramDragBehavior.Pan; + Assert.True(diagram.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, false, true, 0, 0, 0, 0, 0, 0, string.Empty, true), DiagramDragBehavior.Pan)); + } + + [Fact] + public void DiagramBehaviorOptions_CtrlDragBehavior_IsEnabled() + { + var diagram = new TestDiagram(); + diagram.Options.Behaviors.DiagramCtrlDragBehavior = DiagramDragBehavior.None; + Assert.False(diagram.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, true, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true), DiagramDragBehavior.Pan)); + + diagram.Options.Behaviors.DiagramCtrlDragBehavior = DiagramDragBehavior.Pan; + Assert.True(diagram.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, true, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true), DiagramDragBehavior.Pan)); + } + + [Fact] + public void DiagramBehaviorOptions_ShiftDragBehavior_IsEnabled() + { + var diagram = new TestDiagram(); + diagram.Options.Behaviors.DiagramShiftDragBehavior = DiagramDragBehavior.None; + Assert.False(diagram.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, true, false, 0, 0, 0, 0, 0, 0, string.Empty, true), DiagramDragBehavior.Pan)); + + diagram.Options.Behaviors.DiagramShiftDragBehavior = DiagramDragBehavior.Pan; + Assert.True(diagram.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, true, false, 0, 0, 0, 0, 0, 0, string.Empty, true), DiagramDragBehavior.Pan)); + } + + [Fact] + public void DiagramBehaviorOptions_DefaultScrollBehavior_IsEnabled() + { + var diagram = new TestDiagram(); + diagram.Options.Behaviors.DiagramWheelBehavior = DiagramWheelBehavior.None; + Assert.False(diagram.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, false, false, 0, 0, 0, 0), DiagramWheelBehavior.Zoom)); + + diagram.Options.Behaviors.DiagramWheelBehavior = DiagramWheelBehavior.Zoom; + Assert.True(diagram.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, false, false, 0, 0, 0, 0), DiagramWheelBehavior.Zoom)); + } + + [Fact] + public void DiagramBehaviorOptions_AltScrollBehavior_IsEnabled() + { + var diagram = new TestDiagram(); + diagram.Options.Behaviors.DiagramAltWheelBehavior = DiagramWheelBehavior.None; + Assert.False(diagram.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, false, true, 0, 0, 0, 0), DiagramWheelBehavior.Zoom)); + + diagram.Options.Behaviors.DiagramAltWheelBehavior = DiagramWheelBehavior.Zoom; + Assert.True(diagram.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, false, true, 0, 0, 0, 0), DiagramWheelBehavior.Zoom)); + } + + [Fact] + public void DiagramBehaviorOptions_CtrlScrollBehavior_IsEnabled() + { + var diagram = new TestDiagram(); + diagram.Options.Behaviors.DiagramCtrlWheelBehavior = DiagramWheelBehavior.None; + Assert.False(diagram.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, true, false, false, 0, 0, 0, 0), DiagramWheelBehavior.Zoom)); + + diagram.Options.Behaviors.DiagramCtrlWheelBehavior = DiagramWheelBehavior.Zoom; + Assert.True(diagram.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, true, false, false, 0, 0, 0, 0), DiagramWheelBehavior.Zoom)); + } + + [Fact] + public void DiagramBehaviorOptions_ShiftScrollBehavior_IsEnabled() + { + var diagram = new TestDiagram(); + diagram.Options.Behaviors.DiagramShiftWheelBehavior = DiagramWheelBehavior.None; + Assert.False(diagram.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, true, false, 0, 0, 0, 0), DiagramWheelBehavior.Zoom)); + + diagram.Options.Behaviors.DiagramShiftWheelBehavior = DiagramWheelBehavior.Zoom; + Assert.True(diagram.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, true, false, 0, 0, 0, 0), DiagramWheelBehavior.Zoom)); + } + } +} diff --git a/tests/Blazor.Diagrams.Tests/Components/Widgets/SelectionBoxWidgetTests.cs b/tests/Blazor.Diagrams.Tests/Components/Widgets/SelectionBoxWidgetTests.cs new file mode 100644 index 000000000..ef586546c --- /dev/null +++ b/tests/Blazor.Diagrams.Tests/Components/Widgets/SelectionBoxWidgetTests.cs @@ -0,0 +1,52 @@ +using Blazor.Diagrams.Components.Renderers; +using Blazor.Diagrams.Components; +using Blazor.Diagrams.Core.Models; +using Bunit; +using Moq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit; +using Blazor.Diagrams.Components.Widgets; +using AngleSharp.Dom; +using AngleSharp.Css.Dom; +using Blazor.Diagrams.Options; +using Blazor.Diagrams.Core.Options; +using Blazor.Diagrams.Core; +using Blazor.Diagrams.Core.Events; +using Blazor.Diagrams.Core.Geometry; + +namespace Blazor.Diagrams.Tests.Components.Widgets +{ + public class SelectionBoxWidgetTests + { + [Fact] + public void SelectionBoxWidget_SelectionBoundsChanged_RendersSelectionBoxWidgetInCorrectLocation() + { + // Arrange + using var ctx = new TestContext(); + var diagram = new BlazorDiagram(new BlazorDiagramOptions { Behaviors = new DiagramBehaviorOptions { DiagramCtrlDragBehavior = DiagramDragBehavior.Select } }); + diagram.SetPan(-75, -100); + diagram.SetContainer(new Rectangle(new Point(0, 0), new Size(500, 500))); + + // Act + var cut = ctx.RenderComponent(parameters => parameters + .Add(n => n.BlazorDiagram, diagram)); + Assert.Throws(() => cut.Find("div")); + diagram.TriggerPointerDown(null, + new PointerEventArgs(100, 150, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); + diagram.TriggerPointerMove(null, + new PointerEventArgs(200, 250, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); + + + // Assert + var widget = cut.Find("div"); + widget.GetStyle().GetWidth().Equals(100); + widget.GetStyle().GetHeight().Equals(150); + widget.GetStyle().GetTop().Equals(175); + widget.GetStyle().GetLeft().Equals(300); + } + } +} From a21bbaa20ff52877108c7eae36f319b9d0e84278 Mon Sep 17 00:00:00 2001 From: Matt Swain Date: Mon, 15 May 2023 17:41:15 +1000 Subject: [PATCH 02/17] Fixed spelling --- .../{SelectionBoxBehaviour.cs => SelectionBoxBehavior.cs} | 0 .../{DiagramBehaviourOptions.cs => DiagramBehaviorOptions.cs} | 0 .../Behaviors/{PanBehaviourTests.cs => PanBehaviorTests.cs} | 0 .../{ScrollBehaviourTests.cs => ScrollBehaviorTests.cs} | 0 ...lectionBoxBehaviourTests.cs => SelectionBoxBehaviorTests.cs} | 0 .../Behaviors/{ZoomBehaviourTests.cs => ZoomBehaviorTests.cs} | 0 ...mBehaviourOptionsTests.cs => DiagramBehaviorOptionsTests.cs} | 2 +- 7 files changed, 1 insertion(+), 1 deletion(-) rename src/Blazor.Diagrams.Core/Behaviors/{SelectionBoxBehaviour.cs => SelectionBoxBehavior.cs} (100%) rename src/Blazor.Diagrams.Core/Options/{DiagramBehaviourOptions.cs => DiagramBehaviorOptions.cs} (100%) rename tests/Blazor.Diagrams.Core.Tests/Behaviors/{PanBehaviourTests.cs => PanBehaviorTests.cs} (100%) rename tests/Blazor.Diagrams.Core.Tests/Behaviors/{ScrollBehaviourTests.cs => ScrollBehaviorTests.cs} (100%) rename tests/Blazor.Diagrams.Core.Tests/Behaviors/{SelectionBoxBehaviourTests.cs => SelectionBoxBehaviorTests.cs} (100%) rename tests/Blazor.Diagrams.Core.Tests/Behaviors/{ZoomBehaviourTests.cs => ZoomBehaviorTests.cs} (100%) rename tests/Blazor.Diagrams.Core.Tests/Options/{DiagramBehaviourOptionsTests.cs => DiagramBehaviorOptionsTests.cs} (99%) diff --git a/src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehaviour.cs b/src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehavior.cs similarity index 100% rename from src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehaviour.cs rename to src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehavior.cs diff --git a/src/Blazor.Diagrams.Core/Options/DiagramBehaviourOptions.cs b/src/Blazor.Diagrams.Core/Options/DiagramBehaviorOptions.cs similarity index 100% rename from src/Blazor.Diagrams.Core/Options/DiagramBehaviourOptions.cs rename to src/Blazor.Diagrams.Core/Options/DiagramBehaviorOptions.cs diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviourTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviorTests.cs similarity index 100% rename from tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviourTests.cs rename to tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviorTests.cs diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviourTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviorTests.cs similarity index 100% rename from tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviourTests.cs rename to tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviorTests.cs diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviourTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs similarity index 100% rename from tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviourTests.cs rename to tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviourTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviorTests.cs similarity index 100% rename from tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviourTests.cs rename to tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviorTests.cs diff --git a/tests/Blazor.Diagrams.Core.Tests/Options/DiagramBehaviourOptionsTests.cs b/tests/Blazor.Diagrams.Core.Tests/Options/DiagramBehaviorOptionsTests.cs similarity index 99% rename from tests/Blazor.Diagrams.Core.Tests/Options/DiagramBehaviourOptionsTests.cs rename to tests/Blazor.Diagrams.Core.Tests/Options/DiagramBehaviorOptionsTests.cs index de1d30cb9..ccc174c4e 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Options/DiagramBehaviourOptionsTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Options/DiagramBehaviorOptionsTests.cs @@ -9,7 +9,7 @@ namespace Blazor.Diagrams.Core.Tests.Options { - public class DiagramBehaviourOptionsTests + public class DiagramBehaviorOptionsTests { [Fact] public void DiagramBehaviorOptions_DragBehavior_IsEnabled() From 2dfb6e2979f1c493bee471954e23a89dd353b243 Mon Sep 17 00:00:00 2001 From: Matt Swain Date: Mon, 15 May 2023 18:15:35 +1000 Subject: [PATCH 03/17] Added functionality --- .../Behaviors/PanBehavior.cs | 44 +++++------ .../Behaviors/ScrollBehavior.cs | 30 ++++++++ .../Behaviors/SelectionBoxBehavior.cs | 56 +++++++++++++- .../Behaviors/ZoomBehavior.cs | 13 ++-- src/Blazor.Diagrams.Core/Diagram.cs | 54 +++++++++---- .../Options/DiagramOptions.cs | 2 +- .../Widgets/SelectionBoxWidget.razor | 2 +- .../Widgets/SelectionBoxWidget.razor.cs | 76 ++++--------------- .../Options/BlazorDiagramBehaviorOptions.cs | 13 ++++ .../Options/BlazorDiagramOptions.cs | 1 + .../Behaviors/PanBehaviorTests.cs | 5 +- .../Behaviors/ScrollBehaviorTests.cs | 9 ++- .../Behaviors/SelectionBoxBehaviorTests.cs | 16 ++-- .../Behaviors/ZoomBehaviorTests.cs | 2 +- .../Widgets/SelectionBoxWidgetTests.cs | 3 +- 15 files changed, 200 insertions(+), 126 deletions(-) create mode 100644 src/Blazor.Diagrams.Core/Behaviors/ScrollBehavior.cs create mode 100644 src/Blazor.Diagrams/Options/BlazorDiagramBehaviorOptions.cs diff --git a/src/Blazor.Diagrams.Core/Behaviors/PanBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/PanBehavior.cs index bb4d974b7..cbd35a377 100644 --- a/src/Blazor.Diagrams.Core/Behaviors/PanBehavior.cs +++ b/src/Blazor.Diagrams.Core/Behaviors/PanBehavior.cs @@ -1,6 +1,7 @@ using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Core.Models.Base; using Blazor.Diagrams.Core.Events; +using Blazor.Diagrams.Core.Options; namespace Blazor.Diagrams.Core.Behaviors; @@ -17,45 +18,34 @@ public PanBehavior(Diagram diagram) : base(diagram) Diagram.PointerUp += OnPointerUp; } - private void OnPointerDown(Model? model, PointerEventArgs e) - { - if (e.Button != (int)MouseEventButton.Left) - return; + private void OnPointerDown(Model? model, PointerEventArgs e) + { + if (e.Button != (int)MouseEventButton.Left || model != null || !Diagram.Options.AllowPanning || !Diagram.IsBehaviorEnabled(e, DiagramDragBehavior.Pan)) + return; - Start(model, e.ClientX, e.ClientY, e.ShiftKey); - } + _initialPan = Diagram.Pan; + _lastClientX = e.ClientX; + _lastClientY = e.ClientY; + } private void OnPointerMove(Model? model, PointerEventArgs e) => Move(e.ClientX, e.ClientY); private void OnPointerUp(Model? model, PointerEventArgs e) => End(); - private void Start(Model? model, double clientX, double clientY, bool shiftKey) - { - if (!Diagram.Options.AllowPanning || model != null || shiftKey) - return; - - _initialPan = Diagram.Pan; - _lastClientX = clientX; - _lastClientY = clientY; - } - - private void Move(double clientX, double clientY) - { - if (!Diagram.Options.AllowPanning || _initialPan == null) - return; + private void Move(double clientX, double clientY) + { + if (_initialPan == null) + return; var deltaX = clientX - _lastClientX - (Diagram.Pan.X - _initialPan.X); var deltaY = clientY - _lastClientY - (Diagram.Pan.Y - _initialPan.Y); Diagram.UpdatePan(deltaX, deltaY); } - private void End() - { - if (!Diagram.Options.AllowPanning) - return; - - _initialPan = null; - } + private void End() + { + _initialPan = null; + } public override void Dispose() { diff --git a/src/Blazor.Diagrams.Core/Behaviors/ScrollBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/ScrollBehavior.cs new file mode 100644 index 000000000..ca9652d24 --- /dev/null +++ b/src/Blazor.Diagrams.Core/Behaviors/ScrollBehavior.cs @@ -0,0 +1,30 @@ +using Blazor.Diagrams.Core.Events; +using Blazor.Diagrams.Core.Options; + +namespace Blazor.Diagrams.Core.Behaviors +{ + public class ScrollBehavior : Behavior + { + public ScrollBehavior(Diagram diagram) + : base(diagram) + { + Diagram.Wheel += Diagram_Wheel; + } + + void Diagram_Wheel(WheelEventArgs e) + { + if (Diagram.Container == null || !Diagram.IsBehaviorEnabled(e, DiagramWheelBehavior.Scroll)) + return; + + var x = Diagram.Pan.X + (e.DeltaX / Diagram.Options.Zoom.ScaleFactor); + var y = Diagram.Pan.Y + (e.DeltaY / Diagram.Options.Zoom.ScaleFactor); + + Diagram.SetPan(x, y); + } + + public override void Dispose() + { + Diagram.Wheel -= Diagram_Wheel; + } + } +} diff --git a/src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehavior.cs index d4fbca578..4e625b851 100644 --- a/src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehavior.cs +++ b/src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehavior.cs @@ -1,4 +1,7 @@ -using Blazor.Diagrams.Core.Geometry; +using Blazor.Diagrams.Core.Events; +using Blazor.Diagrams.Core.Geometry; +using Blazor.Diagrams.Core.Models.Base; +using Blazor.Diagrams.Core.Options; using System; using System.Collections.Generic; using System.Linq; @@ -9,15 +12,62 @@ namespace Blazor.Diagrams.Core.Behaviors { public class SelectionBoxBehavior : Behavior { + private Point? _initialClientPoint; + + public event EventHandler? SelectionBoundsChanged; + public SelectionBoxBehavior(Diagram diagram) : base(diagram) { + Diagram.PointerDown += OnPointerDown; + Diagram.PointerMove += OnPointerMove; + Diagram.PointerUp += OnPointerUp; } - public event EventHandler BoundsChanged; - public override void Dispose() { + Diagram.PointerDown -= OnPointerDown; + Diagram.PointerMove -= OnPointerMove; + Diagram.PointerUp -= OnPointerUp; + } + + private void OnPointerDown(Model? model, PointerEventArgs e) + { + if (SelectionBoundsChanged is null || model != null || !Diagram.IsBehaviorEnabled(e, DiagramDragBehavior.Select)) + return; + + _initialClientPoint = new Point(e.ClientX, e.ClientY); + } + + private void OnPointerMove(Model? model, PointerEventArgs e) + { + if (_initialClientPoint == null) + return; + + 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); + + SelectionBoundsChanged?.Invoke(this, bounds); + + 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); + } + } + + private void OnPointerUp(Model? model, PointerEventArgs e) + { + _initialClientPoint = null; + SelectionBoundsChanged?.Invoke(this, null); } } } diff --git a/src/Blazor.Diagrams.Core/Behaviors/ZoomBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/ZoomBehavior.cs index 3da507b75..372491c4a 100644 --- a/src/Blazor.Diagrams.Core/Behaviors/ZoomBehavior.cs +++ b/src/Blazor.Diagrams.Core/Behaviors/ZoomBehavior.cs @@ -1,6 +1,6 @@ using Blazor.Diagrams.Core.Events; - using System; +using Blazor.Diagrams.Core.Options; namespace Blazor.Diagrams.Core.Behaviors; @@ -11,13 +11,10 @@ public ZoomBehavior(Diagram diagram) : base(diagram) Diagram.Wheel += Diagram_Wheel; } - private void Diagram_Wheel(WheelEventArgs e) - { - if (Diagram.Container == null || e.DeltaY == 0) - return; - - if (!Diagram.Options.Zoom.Enabled) - return; + private void Diagram_Wheel(WheelEventArgs e) + { + if (Diagram.Container == null || e.DeltaY == 0 || !Diagram.Options.Zoom.Enabled || !Diagram.IsBehaviorEnabled(e, DiagramWheelBehavior.Zoom)) + return; var scale = Diagram.Options.Zoom.ScaleFactor; var oldZoom = Diagram.Zoom; diff --git a/src/Blazor.Diagrams.Core/Diagram.cs b/src/Blazor.Diagrams.Core/Diagram.cs index 9b676aced..d0527de63 100644 --- a/src/Blazor.Diagrams.Core/Diagram.cs +++ b/src/Blazor.Diagrams.Core/Diagram.cs @@ -56,16 +56,18 @@ protected Diagram() Links.Removed += OnSelectableRemoved; Groups.Removed += OnSelectableRemoved; - RegisterBehavior(new SelectionBehavior(this)); - RegisterBehavior(new DragMovablesBehavior(this)); - RegisterBehavior(new DragNewLinkBehavior(this)); - RegisterBehavior(new PanBehavior(this)); - RegisterBehavior(new ZoomBehavior(this)); - RegisterBehavior(new EventsBehavior(this)); - RegisterBehavior(new KeyboardShortcutsBehavior(this)); - RegisterBehavior(new ControlsBehavior(this)); - RegisterBehavior(new VirtualizationBehavior(this)); - } + RegisterBehavior(new SelectionBehavior(this)); + RegisterBehavior(new DragMovablesBehavior(this)); + RegisterBehavior(new DragNewLinkBehavior(this)); + RegisterBehavior(new PanBehavior(this)); + RegisterBehavior(new ZoomBehavior(this)); + RegisterBehavior(new EventsBehavior(this)); + RegisterBehavior(new KeyboardShortcutsBehavior(this)); + RegisterBehavior(new ControlsBehavior(this)); + RegisterBehavior(new VirtualizationBehavior(this)); + RegisterBehavior(new ScrollBehavior(this)); + RegisterBehavior(new SelectionBoxBehavior(this)); + } public abstract DiagramOptions Options { get; } public NodeLayer Nodes { get; } @@ -404,14 +406,38 @@ private void OnModelOrderChanged(Model model) #endregion - public virtual bool IsBehaviorEnabled(PointerEventArgs e, DiagramDragBehavior Behavior) + public virtual bool IsBehaviorEnabled(PointerEventArgs e, DiagramDragBehavior behavior) { - return false; + if (e.AltKey && !e.CtrlKey && !e.ShiftKey) + { + return behavior == Options.Behaviors.DiagramAltDragBehavior; + } + if (e.CtrlKey && !e.AltKey && !e.ShiftKey) + { + return behavior == Options.Behaviors.DiagramCtrlDragBehavior; + } + if (e.ShiftKey && !e.AltKey && !e.CtrlKey) + { + return behavior == Options.Behaviors.DiagramShiftDragBehavior; + } + return behavior == Options.Behaviors.DiagramDragBehavior; } - public virtual bool IsBehaviorEnabled(WheelEventArgs e, DiagramWheelBehavior Behavior) + public virtual bool IsBehaviorEnabled(WheelEventArgs e, DiagramWheelBehavior behavior) { - return false; + if (e.AltKey && !e.CtrlKey && !e.ShiftKey) + { + return behavior == Options.Behaviors.DiagramAltWheelBehavior; + } + if (e.CtrlKey && !e.AltKey && !e.ShiftKey) + { + return behavior == Options.Behaviors.DiagramCtrlWheelBehavior; + } + if (e.ShiftKey && !e.AltKey && !e.CtrlKey) + { + return behavior == Options.Behaviors.DiagramShiftWheelBehavior; + } + return behavior == Options.Behaviors.DiagramWheelBehavior; } } } \ No newline at end of file diff --git a/src/Blazor.Diagrams.Core/Options/DiagramOptions.cs b/src/Blazor.Diagrams.Core/Options/DiagramOptions.cs index b99331836..ab1739211 100644 --- a/src/Blazor.Diagrams.Core/Options/DiagramOptions.cs +++ b/src/Blazor.Diagrams.Core/Options/DiagramOptions.cs @@ -12,5 +12,5 @@ public class DiagramOptions public virtual DiagramGroupOptions Groups { get; } = new(); public virtual DiagramConstraintsOptions Constraints { get; } = new(); public virtual DiagramVirtualizationOptions Virtualization { get; } = new(); - public virtual DiagramBehaviorOptions Behaviors { get; init; } = new(); + public virtual DiagramBehaviorOptions Behaviors { get; } = new(); } \ No newline at end of file diff --git a/src/Blazor.Diagrams/Components/Widgets/SelectionBoxWidget.razor b/src/Blazor.Diagrams/Components/Widgets/SelectionBoxWidget.razor index 4ad4e761e..5cfa9417e 100644 --- a/src/Blazor.Diagrams/Components/Widgets/SelectionBoxWidget.razor +++ b/src/Blazor.Diagrams/Components/Widgets/SelectionBoxWidget.razor @@ -1,4 +1,4 @@ -@if (_selectionBoxTopLeft != null && _selectionBoxSize != null) +@if (_selectionBounds is not null) {
} \ No newline at end of file diff --git a/src/Blazor.Diagrams/Components/Widgets/SelectionBoxWidget.razor.cs b/src/Blazor.Diagrams/Components/Widgets/SelectionBoxWidget.razor.cs index 738fabf1a..07e896bef 100644 --- a/src/Blazor.Diagrams/Components/Widgets/SelectionBoxWidget.razor.cs +++ b/src/Blazor.Diagrams/Components/Widgets/SelectionBoxWidget.razor.cs @@ -1,4 +1,5 @@ using System; +using Blazor.Diagrams.Core.Behaviors; using Blazor.Diagrams.Core.Events; using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Core.Models.Base; @@ -8,9 +9,8 @@ namespace Blazor.Diagrams.Components.Widgets; public partial class SelectionBoxWidget : IDisposable { - private Point? _initialClientPoint; - private Size? _selectionBoxSize; // Todo: remove unneeded instantiations - private Point? _selectionBoxTopLeft; // Todo: remove unneeded instantiations + private Rectangle? _selectionBounds; + private SelectionBoxBehavior? _selectionBoxBehavior; [CascadingParameter] public BlazorDiagram BlazorDiagram { get; set; } = null!; @@ -18,74 +18,30 @@ public partial class SelectionBoxWidget : IDisposable public void Dispose() { - BlazorDiagram.PointerDown -= OnPointerDown; - BlazorDiagram.PointerMove -= OnPointerMove; - BlazorDiagram.PointerUp -= OnPointerUp; + if (_selectionBoxBehavior is not null) + { + _selectionBoxBehavior.SelectionBoundsChanged -= SelectionBoundsChanged; + } } protected override void OnInitialized() { - BlazorDiagram.PointerDown += OnPointerDown; - BlazorDiagram.PointerMove += OnPointerMove; - BlazorDiagram.PointerUp += OnPointerUp; - } - - private string GenerateStyle() - { - return FormattableString.Invariant( - $"position: absolute; background: {Background}; top: {_selectionBoxTopLeft!.Y}px; left: {_selectionBoxTopLeft.X}px; width: {_selectionBoxSize!.Width}px; height: {_selectionBoxSize.Height}px;"); - } - - private void OnPointerDown(Model? model, MouseEventArgs e) - { - if (model != null || !e.ShiftKey) - return; - - _initialClientPoint = new Point(e.ClientX, e.ClientY); - } - - private void OnPointerMove(Model? model, MouseEventArgs e) - { - if (_initialClientPoint == null) - return; - - SetSelectionBoxInformation(e); - - var start = BlazorDiagram.GetRelativeMousePoint(_initialClientPoint.X, _initialClientPoint.Y); - var end = BlazorDiagram.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 BlazorDiagram.Nodes) + _selectionBoxBehavior = BlazorDiagram.GetBehavior(); + if (_selectionBoxBehavior is not null) { - var nodeBounds = node.GetBounds(); - if (nodeBounds == null) - continue; - - if (bounds.Overlap(nodeBounds)) - BlazorDiagram.SelectModel(node, false); - else if (node.Selected) BlazorDiagram.UnselectModel(node); + _selectionBoxBehavior.SelectionBoundsChanged += SelectionBoundsChanged; } - - InvokeAsync(StateHasChanged); } - private void SetSelectionBoxInformation(MouseEventArgs e) + void SelectionBoundsChanged(object? sender, Rectangle? bounds) { - var start = BlazorDiagram.GetRelativePoint(_initialClientPoint!.X, _initialClientPoint.Y); - var end = BlazorDiagram.GetRelativePoint(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)); - _selectionBoxTopLeft = new Point(sX, sY); - _selectionBoxSize = new Size(eX - sX, eY - sY); + _selectionBounds = bounds; + InvokeAsync(StateHasChanged); } - private void OnPointerUp(Model? model, MouseEventArgs e) + private string GenerateStyle() { - _initialClientPoint = null; - _selectionBoxTopLeft = null; - _selectionBoxSize = null; - InvokeAsync(StateHasChanged); + return FormattableString.Invariant( + $"position: absolute; background: {Background}; top: {_selectionBounds!.Top + BlazorDiagram.Pan.Y}px; left: {_selectionBounds.Left + BlazorDiagram.Pan.X}px; width: {_selectionBounds.Width}px; height: {_selectionBounds.Height}px;"); } } \ No newline at end of file diff --git a/src/Blazor.Diagrams/Options/BlazorDiagramBehaviorOptions.cs b/src/Blazor.Diagrams/Options/BlazorDiagramBehaviorOptions.cs new file mode 100644 index 000000000..82643a268 --- /dev/null +++ b/src/Blazor.Diagrams/Options/BlazorDiagramBehaviorOptions.cs @@ -0,0 +1,13 @@ +using Blazor.Diagrams.Core.Options; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Blazor.Diagrams.Options +{ + public class BlazorDiagramBehaviorOptions : DiagramBehaviorOptions + { + } +} diff --git a/src/Blazor.Diagrams/Options/BlazorDiagramOptions.cs b/src/Blazor.Diagrams/Options/BlazorDiagramOptions.cs index b7ea0e63e..11093f5b0 100644 --- a/src/Blazor.Diagrams/Options/BlazorDiagramOptions.cs +++ b/src/Blazor.Diagrams/Options/BlazorDiagramOptions.cs @@ -12,4 +12,5 @@ public class BlazorDiagramOptions : DiagramOptions public override BlazorDiagramGroupOptions Groups { get; } = new(); public override BlazorDiagramConstraintsOptions Constraints { get; } = new(); public override BlazorDiagramVirtualizationOptions Virtualization { get; } = new(); + public override BlazorDiagramBehaviorOptions Behaviors { get; } = new(); } \ No newline at end of file diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviorTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviorTests.cs index f0c04c255..8b06177bc 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviorTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviorTests.cs @@ -1,4 +1,5 @@ using Blazor.Diagrams.Core.Events; +using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Core.Options; using Moq; using Xunit; @@ -12,7 +13,8 @@ public void Behavior_WhenBehaviorEnabled_ShouldPan() { // Arrange var diagram = new Mock(null) { CallBase = true }; - diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns(true); + diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns((PointerEventArgs _, DiagramDragBehavior behaviour) => behaviour == DiagramDragBehavior.Pan); + diagram.Object.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); Assert.Equal(0, diagram.Object.Pan.X); Assert.Equal(0, diagram.Object.Pan.Y); @@ -34,6 +36,7 @@ public void Behavior_WhenBehaviorDisabled_ShouldNotPan() // Arrange var diagram = new Mock(null) { CallBase = true }; diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns(false); + diagram.Object.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); Assert.Equal(0, diagram.Object.Pan.X); Assert.Equal(0, diagram.Object.Pan.Y); diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviorTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviorTests.cs index 7f0d35c0e..f759f5385 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviorTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviorTests.cs @@ -1,4 +1,5 @@ using Blazor.Diagrams.Core.Events; +using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Core.Options; using Moq; using Xunit; @@ -12,14 +13,15 @@ public void Behavior_WhenBehaviorEnabled_ShouldScroll() { // Arrange var diagram = new Mock(null) { CallBase = true }; - diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns(true); + diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns((WheelEventArgs _, DiagramWheelBehavior behaviour) => behaviour == DiagramWheelBehavior.Scroll); + diagram.Object.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); // Act diagram.Object.TriggerWheel(new WheelEventArgs(100, 100, 0, 0, false, false, false, 100, 200, 0, 0)); // Assert - Assert.Equal(100, diagram.Object.Pan.X); - Assert.Equal(200, diagram.Object.Pan.Y); + Assert.Equal(95, diagram.Object.Pan.X, 0); + Assert.Equal(190, diagram.Object.Pan.Y, 0); } [Fact] @@ -28,6 +30,7 @@ public void Behavior_WhenBehaviorDisabled_ShouldNotScroll() // Arrange var diagram = new Mock(null) { CallBase = true }; diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns(false); + diagram.Object.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); // Act diagram.Object.TriggerWheel(new WheelEventArgs(100, 100, 0, 0, false, false, false, 100, 200, 0, 0)); diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs index 9ddd36e98..fbd77f91c 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs @@ -15,12 +15,13 @@ public void Behavior_WhenBehaviorEnabled_ShouldUpdateSelectionBounds() { // Arrange var diagram = new Mock(null) { CallBase = true }; - diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns(true); + diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns((PointerEventArgs _, DiagramDragBehavior behaviour) => behaviour == DiagramDragBehavior.Select); + diagram.Object.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); var selectionBoxBehavior = diagram.Object.GetBehavior()!; bool boundsChangedEventInvoked = false; Rectangle? lastBounds = null; - selectionBoxBehavior.BoundsChanged += (_, newBounds) => + selectionBoxBehavior.SelectionBoundsChanged += (_, newBounds) => { boundsChangedEventInvoked = true; lastBounds = newBounds; @@ -46,11 +47,12 @@ public void Behavior_WhenBehaviorDisabled_ShouldNotUpdateSelectionBounds() // Arrange var diagram = new Mock(null) { CallBase = true }; diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns(false); + diagram.Object.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); var selectionBoxBehavior = diagram.Object.GetBehavior()!; bool boundsChangedEventInvoked = false; Rectangle? lastBounds = null; - selectionBoxBehavior.BoundsChanged += (_, newBounds) => + selectionBoxBehavior.SelectionBoundsChanged += (_, newBounds) => { boundsChangedEventInvoked = true; lastBounds = newBounds; @@ -72,10 +74,11 @@ public void Behavior_WithBoundsChangedDelegate_ShouldSelectNodesInsideArea() { // Arrange var diagram = new Mock(null) { CallBase = true }; - diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns(true); + diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns((PointerEventArgs _, DiagramDragBehavior behaviour) => behaviour == DiagramDragBehavior.Select); + diagram.Object.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); var selectionBoxBehavior = diagram.Object.GetBehavior()!; - selectionBoxBehavior.BoundsChanged += (_, _) => { }; + selectionBoxBehavior.SelectionBoundsChanged += (_, _) => { }; var node = new NodeModel() { @@ -103,7 +106,8 @@ public void Behavior_WithoutBoundsChangedDelegate_ShouldNotSelectNodesInsideArea { // Arrange var diagram = new Mock(null) { CallBase = true }; - diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns(true); + diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns((PointerEventArgs _, DiagramDragBehavior behaviour) => behaviour == DiagramDragBehavior.Select); + diagram.Object.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); var node = new NodeModel() { diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviorTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviorTests.cs index 26d58dcb4..a9401b9e7 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviorTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviorTests.cs @@ -13,7 +13,7 @@ public void Behavior_WhenBehaviorEnabled_ShouldZoom() { // Arrange var diagram = new Mock(null) { CallBase = true }; - diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns(true); + diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns((WheelEventArgs _, DiagramWheelBehavior behaviour) => behaviour == DiagramWheelBehavior.Zoom); diagram.Object.SetContainer(new Rectangle(0, 0, 100, 100)); // Act diff --git a/tests/Blazor.Diagrams.Tests/Components/Widgets/SelectionBoxWidgetTests.cs b/tests/Blazor.Diagrams.Tests/Components/Widgets/SelectionBoxWidgetTests.cs index ef586546c..8f832ea7f 100644 --- a/tests/Blazor.Diagrams.Tests/Components/Widgets/SelectionBoxWidgetTests.cs +++ b/tests/Blazor.Diagrams.Tests/Components/Widgets/SelectionBoxWidgetTests.cs @@ -27,7 +27,8 @@ public void SelectionBoxWidget_SelectionBoundsChanged_RendersSelectionBoxWidgetI { // Arrange using var ctx = new TestContext(); - var diagram = new BlazorDiagram(new BlazorDiagramOptions { Behaviors = new DiagramBehaviorOptions { DiagramCtrlDragBehavior = DiagramDragBehavior.Select } }); + var diagram = new BlazorDiagram(); + diagram.Options.Behaviors.DiagramDragBehavior = DiagramDragBehavior.Select; diagram.SetPan(-75, -100); diagram.SetContainer(new Rectangle(new Point(0, 0), new Size(500, 500))); From c4d19e2ca6ad5fbdecd9003211ee1dc0b4679e50 Mon Sep 17 00:00:00 2001 From: Matt Swain Date: Thu, 18 May 2023 10:59:45 +1000 Subject: [PATCH 04/17] fixed code review comments --- src/Blazor.Diagrams.Core/Behaviors/ScrollBehavior.cs | 2 +- .../Behaviors/PanBehaviorTests.cs | 6 ++++-- .../Behaviors/ScrollBehaviorTests.cs | 9 ++++++--- .../Behaviors/SelectionBoxBehaviorTests.cs | 12 ++++++++---- .../Behaviors/ZoomBehaviorTests.cs | 6 ++++-- .../Components/Widgets/SelectionBoxWidgetTests.cs | 8 ++++---- 6 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/Blazor.Diagrams.Core/Behaviors/ScrollBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/ScrollBehavior.cs index ca9652d24..4039de0e6 100644 --- a/src/Blazor.Diagrams.Core/Behaviors/ScrollBehavior.cs +++ b/src/Blazor.Diagrams.Core/Behaviors/ScrollBehavior.cs @@ -17,7 +17,7 @@ void Diagram_Wheel(WheelEventArgs e) return; var x = Diagram.Pan.X + (e.DeltaX / Diagram.Options.Zoom.ScaleFactor); - var y = Diagram.Pan.Y + (e.DeltaY / Diagram.Options.Zoom.ScaleFactor); + var y = Diagram.Pan.Y - (e.DeltaY / Diagram.Options.Zoom.ScaleFactor); Diagram.SetPan(x, y); } diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviorTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviorTests.cs index 8b06177bc..8ad20abb5 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviorTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviorTests.cs @@ -13,7 +13,8 @@ public void Behavior_WhenBehaviorEnabled_ShouldPan() { // Arrange var diagram = new Mock(null) { CallBase = true }; - diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns((PointerEventArgs _, DiagramDragBehavior behaviour) => behaviour == DiagramDragBehavior.Pan); + diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())) + .Returns((PointerEventArgs _, DiagramDragBehavior behaviour) => behaviour == DiagramDragBehavior.Pan); diagram.Object.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); Assert.Equal(0, diagram.Object.Pan.X); @@ -35,7 +36,8 @@ public void Behavior_WhenBehaviorDisabled_ShouldNotPan() { // Arrange var diagram = new Mock(null) { CallBase = true }; - diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns(false); + diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())) + .Returns(false); diagram.Object.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); Assert.Equal(0, diagram.Object.Pan.X); diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviorTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviorTests.cs index f759f5385..847be6c98 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviorTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviorTests.cs @@ -13,15 +13,17 @@ public void Behavior_WhenBehaviorEnabled_ShouldScroll() { // Arrange var diagram = new Mock(null) { CallBase = true }; - diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns((WheelEventArgs _, DiagramWheelBehavior behaviour) => behaviour == DiagramWheelBehavior.Scroll); + diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())) + .Returns((WheelEventArgs _, DiagramWheelBehavior behaviour) => behaviour == DiagramWheelBehavior.Scroll); diagram.Object.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); + diagram.Object.Options.Zoom.ScaleFactor = 1.05; // Act diagram.Object.TriggerWheel(new WheelEventArgs(100, 100, 0, 0, false, false, false, 100, 200, 0, 0)); // Assert Assert.Equal(95, diagram.Object.Pan.X, 0); - Assert.Equal(190, diagram.Object.Pan.Y, 0); + Assert.Equal(-190, diagram.Object.Pan.Y, 0); } [Fact] @@ -29,7 +31,8 @@ public void Behavior_WhenBehaviorDisabled_ShouldNotScroll() { // Arrange var diagram = new Mock(null) { CallBase = true }; - diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns(false); + diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())) + .Returns(false); diagram.Object.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); // Act diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs index fbd77f91c..4a93c8c7e 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs @@ -15,7 +15,8 @@ public void Behavior_WhenBehaviorEnabled_ShouldUpdateSelectionBounds() { // Arrange var diagram = new Mock(null) { CallBase = true }; - diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns((PointerEventArgs _, DiagramDragBehavior behaviour) => behaviour == DiagramDragBehavior.Select); + diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())) + .Returns((PointerEventArgs _, DiagramDragBehavior behaviour) => behaviour == DiagramDragBehavior.Select); diagram.Object.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); var selectionBoxBehavior = diagram.Object.GetBehavior()!; @@ -46,7 +47,8 @@ public void Behavior_WhenBehaviorDisabled_ShouldNotUpdateSelectionBounds() { // Arrange var diagram = new Mock(null) { CallBase = true }; - diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns(false); + diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())) + .Returns(false); diagram.Object.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); var selectionBoxBehavior = diagram.Object.GetBehavior()!; @@ -74,7 +76,8 @@ public void Behavior_WithBoundsChangedDelegate_ShouldSelectNodesInsideArea() { // Arrange var diagram = new Mock(null) { CallBase = true }; - diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns((PointerEventArgs _, DiagramDragBehavior behaviour) => behaviour == DiagramDragBehavior.Select); + diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())) + .Returns((PointerEventArgs _, DiagramDragBehavior behaviour) => behaviour == DiagramDragBehavior.Select); diagram.Object.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); var selectionBoxBehavior = diagram.Object.GetBehavior()!; @@ -106,7 +109,8 @@ public void Behavior_WithoutBoundsChangedDelegate_ShouldNotSelectNodesInsideArea { // Arrange var diagram = new Mock(null) { CallBase = true }; - diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns((PointerEventArgs _, DiagramDragBehavior behaviour) => behaviour == DiagramDragBehavior.Select); + diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())) + .Returns((PointerEventArgs _, DiagramDragBehavior behaviour) => behaviour == DiagramDragBehavior.Select); diagram.Object.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); var node = new NodeModel() diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviorTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviorTests.cs index a9401b9e7..6086ba3f3 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviorTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviorTests.cs @@ -13,7 +13,8 @@ public void Behavior_WhenBehaviorEnabled_ShouldZoom() { // Arrange var diagram = new Mock(null) { CallBase = true }; - diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns((WheelEventArgs _, DiagramWheelBehavior behaviour) => behaviour == DiagramWheelBehavior.Zoom); + diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())) + .Returns((WheelEventArgs _, DiagramWheelBehavior behaviour) => behaviour == DiagramWheelBehavior.Zoom); diagram.Object.SetContainer(new Rectangle(0, 0, 100, 100)); // Act @@ -28,7 +29,8 @@ public void Behavior_WhenBehaviorDisabled_ShouldNotZoom() { // Arrange var diagram = new Mock(null) { CallBase = true }; - diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())).Returns(false); + diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())) + .Returns(false); diagram.Object.SetContainer(new Rectangle(0, 0, 100, 100)); // Act diff --git a/tests/Blazor.Diagrams.Tests/Components/Widgets/SelectionBoxWidgetTests.cs b/tests/Blazor.Diagrams.Tests/Components/Widgets/SelectionBoxWidgetTests.cs index 8f832ea7f..d1f3b686c 100644 --- a/tests/Blazor.Diagrams.Tests/Components/Widgets/SelectionBoxWidgetTests.cs +++ b/tests/Blazor.Diagrams.Tests/Components/Widgets/SelectionBoxWidgetTests.cs @@ -44,10 +44,10 @@ public void SelectionBoxWidget_SelectionBoundsChanged_RendersSelectionBoxWidgetI // Assert var widget = cut.Find("div"); - widget.GetStyle().GetWidth().Equals(100); - widget.GetStyle().GetHeight().Equals(150); - widget.GetStyle().GetTop().Equals(175); - widget.GetStyle().GetLeft().Equals(300); + Assert.Equal("100px", widget.GetStyle().GetWidth()); + Assert.Equal("100px", widget.GetStyle().GetHeight()); + Assert.Equal("150px", widget.GetStyle().GetTop()); + Assert.Equal("100px", widget.GetStyle().GetLeft()); } } } From 8d86551b48cad2ff72e8aa03e74d86232659ddfb Mon Sep 17 00:00:00 2001 From: Matt Swain Date: Thu, 18 May 2023 11:04:11 +1000 Subject: [PATCH 05/17] Fixed scroll behaviour --- src/Blazor.Diagrams.Core/Behaviors/ScrollBehavior.cs | 2 +- .../Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviorTests.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Blazor.Diagrams.Core/Behaviors/ScrollBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/ScrollBehavior.cs index 4039de0e6..10d535426 100644 --- a/src/Blazor.Diagrams.Core/Behaviors/ScrollBehavior.cs +++ b/src/Blazor.Diagrams.Core/Behaviors/ScrollBehavior.cs @@ -16,7 +16,7 @@ void Diagram_Wheel(WheelEventArgs e) if (Diagram.Container == null || !Diagram.IsBehaviorEnabled(e, DiagramWheelBehavior.Scroll)) return; - var x = Diagram.Pan.X + (e.DeltaX / Diagram.Options.Zoom.ScaleFactor); + var x = Diagram.Pan.X - (e.DeltaX / Diagram.Options.Zoom.ScaleFactor); var y = Diagram.Pan.Y - (e.DeltaY / Diagram.Options.Zoom.ScaleFactor); Diagram.SetPan(x, y); diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviorTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviorTests.cs index 847be6c98..c3b0eaf17 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviorTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviorTests.cs @@ -22,7 +22,7 @@ public void Behavior_WhenBehaviorEnabled_ShouldScroll() diagram.Object.TriggerWheel(new WheelEventArgs(100, 100, 0, 0, false, false, false, 100, 200, 0, 0)); // Assert - Assert.Equal(95, diagram.Object.Pan.X, 0); + Assert.Equal(-95, diagram.Object.Pan.X, 0); Assert.Equal(-190, diagram.Object.Pan.Y, 0); } From 609b813dbf428571ff5a5ba6733b091c42bfb5ce Mon Sep 17 00:00:00 2001 From: Matt Swain Date: Tue, 23 May 2023 10:21:29 +1000 Subject: [PATCH 06/17] Fixed selection box behaviour --- .../Behaviors/SelectionBoxBehavior.cs | 13 +++++++++++-- .../Components/Widgets/SelectionBoxWidget.razor.cs | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehavior.cs index 4e625b851..46d699e15 100644 --- a/src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehavior.cs +++ b/src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehavior.cs @@ -44,14 +44,14 @@ private void OnPointerMove(Model? model, PointerEventArgs e) if (_initialClientPoint == null) return; + UpdateSelectionBox(e); + 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); - SelectionBoundsChanged?.Invoke(this, bounds); - foreach (var node in Diagram.Nodes) { var nodeBounds = node.GetBounds(); @@ -64,6 +64,15 @@ private void OnPointerMove(Model? model, PointerEventArgs e) } } + void UpdateSelectionBox(MouseEventArgs e) + { + var start = Diagram.GetRelativePoint(_initialClientPoint!.X, _initialClientPoint.Y); + var end = Diagram.GetRelativePoint(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)); + SelectionBoundsChanged?.Invoke(this, new Rectangle(sX, sY, eX, eY)); + } + private void OnPointerUp(Model? model, PointerEventArgs e) { _initialClientPoint = null; diff --git a/src/Blazor.Diagrams/Components/Widgets/SelectionBoxWidget.razor.cs b/src/Blazor.Diagrams/Components/Widgets/SelectionBoxWidget.razor.cs index 07e896bef..988166755 100644 --- a/src/Blazor.Diagrams/Components/Widgets/SelectionBoxWidget.razor.cs +++ b/src/Blazor.Diagrams/Components/Widgets/SelectionBoxWidget.razor.cs @@ -42,6 +42,6 @@ void SelectionBoundsChanged(object? sender, Rectangle? bounds) private string GenerateStyle() { return FormattableString.Invariant( - $"position: absolute; background: {Background}; top: {_selectionBounds!.Top + BlazorDiagram.Pan.Y}px; left: {_selectionBounds.Left + BlazorDiagram.Pan.X}px; width: {_selectionBounds.Width}px; height: {_selectionBounds.Height}px;"); + $"position: absolute; background: {Background}; top: {_selectionBounds!.Top}px; left: {_selectionBounds.Left}px; width: {_selectionBounds.Width}px; height: {_selectionBounds.Height}px;"); } } \ No newline at end of file From f86002e59b2f4b2c5557a0c0c3364cc1d8e0fc86 Mon Sep 17 00:00:00 2001 From: Matt Swain Date: Tue, 23 May 2023 17:31:09 +1000 Subject: [PATCH 07/17] refactored to not use enum --- src/Blazor.Diagrams.Core/Behavior.cs | 15 --- .../Behaviors/Base/Behavior.cs | 15 +++ .../Behaviors/Base/DragBehavior.cs | 51 +++++++++ .../Behaviors/Base/WheelBehavior.cs | 43 +++++++ .../Behaviors/DebugEventsBehavior.cs | 3 +- .../Behaviors/DragMovablesBehavior.cs | 1 + .../Behaviors/DragNewLinkBehavior.cs | 2 +- .../Behaviors/EventsBehavior.cs | 1 + .../Behaviors/KeyboardShortcutsBehavior.cs | 3 +- .../Behaviors/PanBehavior.cs | 49 +++----- .../Behaviors/ScrollBehavior.cs | 15 +-- .../Behaviors/SelectionBehavior.cs | 1 + .../Behaviors/SelectionBoxBehavior.cs | 17 ++- .../Behaviors/VirtualizationBehavior.cs | 1 + .../Behaviors/ZoomBehavior.cs | 35 +++--- .../Controls/ControlsBehavior.cs | 1 + src/Blazor.Diagrams.Core/Diagram.cs | 35 +----- .../Options/DiagramBehaviorOptions.cs | 86 +++++++++----- .../Options/DiagramOptions.cs | 9 +- .../Behaviors/PanBehaviorTests.cs | 43 ++++--- .../Behaviors/ScrollBehaviorTests.cs | 33 +++--- .../Behaviors/SelectionBoxBehaviorTests.cs | 60 +++++----- .../Behaviors/ZoomBehaviorTests.cs | 27 ++--- .../Options/DiagramBehaviorOptionsTests.cs | 107 +++++++++++------- .../Widgets/SelectionBoxWidgetTests.cs | 18 +-- 25 files changed, 376 insertions(+), 295 deletions(-) delete mode 100644 src/Blazor.Diagrams.Core/Behavior.cs create mode 100644 src/Blazor.Diagrams.Core/Behaviors/Base/Behavior.cs create mode 100644 src/Blazor.Diagrams.Core/Behaviors/Base/DragBehavior.cs create mode 100644 src/Blazor.Diagrams.Core/Behaviors/Base/WheelBehavior.cs diff --git a/src/Blazor.Diagrams.Core/Behavior.cs b/src/Blazor.Diagrams.Core/Behavior.cs deleted file mode 100644 index 78e020602..000000000 --- a/src/Blazor.Diagrams.Core/Behavior.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; - -namespace Blazor.Diagrams.Core; - -public abstract class Behavior : IDisposable -{ - public Behavior(Diagram diagram) - { - Diagram = diagram; - } - - protected Diagram Diagram { get; } - - public abstract void Dispose(); -} diff --git a/src/Blazor.Diagrams.Core/Behaviors/Base/Behavior.cs b/src/Blazor.Diagrams.Core/Behaviors/Base/Behavior.cs new file mode 100644 index 000000000..617447e7c --- /dev/null +++ b/src/Blazor.Diagrams.Core/Behaviors/Base/Behavior.cs @@ -0,0 +1,15 @@ +using System; + +namespace Blazor.Diagrams.Core.Behaviors.Base +{ + public abstract class Behavior : IDisposable + { + public Behavior(Diagram diagram) + { + Diagram = diagram; + } + + protected Diagram Diagram { get; } + + public abstract void Dispose(); +} diff --git a/src/Blazor.Diagrams.Core/Behaviors/Base/DragBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/Base/DragBehavior.cs new file mode 100644 index 000000000..bb42fdeff --- /dev/null +++ b/src/Blazor.Diagrams.Core/Behaviors/Base/DragBehavior.cs @@ -0,0 +1,51 @@ +using Blazor.Diagrams.Core.Events; +using Blazor.Diagrams.Core.Models.Base; + +namespace Blazor.Diagrams.Core.Behaviors.Base +{ + public abstract class DragBehavior : Behavior + { + public DragBehavior(Diagram diagram) + : base(diagram) + { + Diagram.PointerDown += OnPointerDown; + Diagram.PointerMove += OnPointerMove; + Diagram.PointerUp += OnPointerUp; + } + + protected abstract void OnPointerDown(Model? model, PointerEventArgs e); + + protected abstract void OnPointerMove(Model? model, PointerEventArgs e); + + protected abstract void OnPointerUp(Model? model, PointerEventArgs e); + + public virtual bool IsBehaviorEnabled(PointerEventArgs e) + { + var dragBehavior = Diagram.Options.Behaviors.DiagramDragBehavior; + if (e.AltKey && !e.CtrlKey && !e.ShiftKey + && Diagram.Options.Behaviors.DiagramAltDragBehavior is not null) + { + dragBehavior = Diagram.Options.Behaviors.DiagramAltDragBehavior; + } + else if (!e.AltKey && e.CtrlKey && !e.ShiftKey + && Diagram.Options.Behaviors.DiagramCtrlDragBehavior is not null) + { + dragBehavior = Diagram.Options.Behaviors.DiagramCtrlDragBehavior; + } + else if (!e.AltKey && !e.CtrlKey && e.ShiftKey + && Diagram.Options.Behaviors.DiagramShiftDragBehavior is not null) + { + dragBehavior = Diagram.Options.Behaviors.DiagramShiftDragBehavior; + } + + return dragBehavior?.IsAssignableFrom(GetType()) ?? false; + } + + public override void Dispose() + { + Diagram.PointerDown -= OnPointerDown; + Diagram.PointerMove -= OnPointerMove; + Diagram.PointerUp -= OnPointerUp; + } + } +} diff --git a/src/Blazor.Diagrams.Core/Behaviors/Base/WheelBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/Base/WheelBehavior.cs new file mode 100644 index 000000000..31ec39814 --- /dev/null +++ b/src/Blazor.Diagrams.Core/Behaviors/Base/WheelBehavior.cs @@ -0,0 +1,43 @@ +using Blazor.Diagrams.Core.Events; + +namespace Blazor.Diagrams.Core.Behaviors.Base +{ + public abstract class WheelBehavior : Behavior + { + protected WheelBehavior(Diagram diagram) + : base(diagram) + { + + Diagram.Wheel += OnDiagramWheel; + } + + protected abstract void OnDiagramWheel(WheelEventArgs e); + + public virtual bool IsBehaviorEnabled(WheelEventArgs e) + { + var wheelBehavior = Diagram.Options.Behaviors.DiagramWheelBehavior; + if (e.AltKey && !e.CtrlKey && !e.ShiftKey + && Diagram.Options.Behaviors.DiagramAltWheelBehavior is not null) + { + wheelBehavior = Diagram.Options.Behaviors.DiagramAltWheelBehavior; + } + else if (!e.AltKey && e.CtrlKey && !e.ShiftKey + && Diagram.Options.Behaviors.DiagramCtrlWheelBehavior is not null) + { + wheelBehavior = Diagram.Options.Behaviors.DiagramCtrlWheelBehavior; + } + else if (!e.AltKey && !e.CtrlKey && e.ShiftKey + && Diagram.Options.Behaviors.DiagramShiftWheelBehavior is not null) + { + wheelBehavior = Diagram.Options.Behaviors.DiagramShiftWheelBehavior; + } + + return wheelBehavior?.IsAssignableFrom(GetType()) ?? false; + } + + public override void Dispose() + { + Diagram.Wheel -= OnDiagramWheel; + } + } +} diff --git a/src/Blazor.Diagrams.Core/Behaviors/DebugEventsBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/DebugEventsBehavior.cs index f3fe081d1..c5f71078d 100644 --- a/src/Blazor.Diagrams.Core/Behaviors/DebugEventsBehavior.cs +++ b/src/Blazor.Diagrams.Core/Behaviors/DebugEventsBehavior.cs @@ -1,4 +1,5 @@ -using Blazor.Diagrams.Core.Models; +using Blazor.Diagrams.Core.Behaviors.Base; +using Blazor.Diagrams.Core.Models; using Blazor.Diagrams.Core.Models.Base; using System; diff --git a/src/Blazor.Diagrams.Core/Behaviors/DragMovablesBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/DragMovablesBehavior.cs index db5aa2c0d..face95c33 100644 --- a/src/Blazor.Diagrams.Core/Behaviors/DragMovablesBehavior.cs +++ b/src/Blazor.Diagrams.Core/Behaviors/DragMovablesBehavior.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using Blazor.Diagrams.Core.Models; +using Blazor.Diagrams.Core.Behaviors.Base; namespace Blazor.Diagrams.Core.Behaviors; diff --git a/src/Blazor.Diagrams.Core/Behaviors/DragNewLinkBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/DragNewLinkBehavior.cs index 31d0c5ede..3796f2c95 100644 --- a/src/Blazor.Diagrams.Core/Behaviors/DragNewLinkBehavior.cs +++ b/src/Blazor.Diagrams.Core/Behaviors/DragNewLinkBehavior.cs @@ -3,7 +3,7 @@ using Blazor.Diagrams.Core.Events; using System.Linq; using Blazor.Diagrams.Core.Anchors; -using Blazor.Diagrams.Core.Geometry; +using Blazor.Diagrams.Core.Behaviors.Base; namespace Blazor.Diagrams.Core.Behaviors; diff --git a/src/Blazor.Diagrams.Core/Behaviors/EventsBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/EventsBehavior.cs index 6bb8bc0c7..705b1d650 100644 --- a/src/Blazor.Diagrams.Core/Behaviors/EventsBehavior.cs +++ b/src/Blazor.Diagrams.Core/Behaviors/EventsBehavior.cs @@ -1,6 +1,7 @@ using Blazor.Diagrams.Core.Models.Base; using Blazor.Diagrams.Core.Events; using System.Diagnostics; +using Blazor.Diagrams.Core.Behaviors.Base; namespace Blazor.Diagrams.Core.Behaviors; diff --git a/src/Blazor.Diagrams.Core/Behaviors/KeyboardShortcutsBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/KeyboardShortcutsBehavior.cs index 5243bed09..6e136e0b5 100644 --- a/src/Blazor.Diagrams.Core/Behaviors/KeyboardShortcutsBehavior.cs +++ b/src/Blazor.Diagrams.Core/Behaviors/KeyboardShortcutsBehavior.cs @@ -1,4 +1,5 @@ -using Blazor.Diagrams.Core.Events; +using Blazor.Diagrams.Core.Behaviors.Base; +using Blazor.Diagrams.Core.Events; using Blazor.Diagrams.Core.Utils; using System; using System.Collections.Generic; diff --git a/src/Blazor.Diagrams.Core/Behaviors/PanBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/PanBehavior.cs index cbd35a377..16f508fe5 100644 --- a/src/Blazor.Diagrams.Core/Behaviors/PanBehavior.cs +++ b/src/Blazor.Diagrams.Core/Behaviors/PanBehavior.cs @@ -1,26 +1,23 @@ using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Core.Models.Base; using Blazor.Diagrams.Core.Events; -using Blazor.Diagrams.Core.Options; +using Blazor.Diagrams.Core.Behaviors.Base; -namespace Blazor.Diagrams.Core.Behaviors; - -public class PanBehavior : Behavior +namespace Blazor.Diagrams.Core.Behaviors { - private Point? _initialPan; - private double _lastClientX; - private double _lastClientY; - - public PanBehavior(Diagram diagram) : base(diagram) + public class PanBehavior : DragBehavior { - Diagram.PointerDown += OnPointerDown; - Diagram.PointerMove += OnPointerMove; - Diagram.PointerUp += OnPointerUp; - } + private Point? _initialPan; + private double _lastClientX; + private double _lastClientY; + + public PanBehavior(Diagram diagram) : base(diagram) + { + } - private void OnPointerDown(Model? model, PointerEventArgs e) + protected override void OnPointerDown(Model? model, PointerEventArgs e) { - if (e.Button != (int)MouseEventButton.Left || model != null || !Diagram.Options.AllowPanning || !Diagram.IsBehaviorEnabled(e, DiagramDragBehavior.Pan)) + if (e.Button != (int)MouseEventButton.Left || model != null || !Diagram.Options.AllowPanning || !IsBehaviorEnabled(e)) return; _initialPan = Diagram.Pan; @@ -28,29 +25,19 @@ private void OnPointerDown(Model? model, PointerEventArgs e) _lastClientY = e.ClientY; } - private void OnPointerMove(Model? model, PointerEventArgs e) => Move(e.ClientX, e.ClientY); - - private void OnPointerUp(Model? model, PointerEventArgs e) => End(); - - private void Move(double clientX, double clientY) + protected override void OnPointerMove(Model? model, PointerEventArgs e) { if (_initialPan == null) return; - var deltaX = clientX - _lastClientX - (Diagram.Pan.X - _initialPan.X); - var deltaY = clientY - _lastClientY - (Diagram.Pan.Y - _initialPan.Y); - Diagram.UpdatePan(deltaX, deltaY); - } + var deltaX = e.ClientX - _lastClientX - (Diagram.Pan.X - _initialPan.X); + var deltaY = e.ClientY - _lastClientY - (Diagram.Pan.Y - _initialPan.Y); + Diagram.UpdatePan(deltaX, deltaY); + } - private void End() + protected override void OnPointerUp(Model? model, PointerEventArgs e) { _initialPan = null; } - - public override void Dispose() - { - Diagram.PointerDown -= OnPointerDown; - Diagram.PointerMove -= OnPointerMove; - Diagram.PointerUp -= OnPointerUp; } } diff --git a/src/Blazor.Diagrams.Core/Behaviors/ScrollBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/ScrollBehavior.cs index 10d535426..fa3ef63e1 100644 --- a/src/Blazor.Diagrams.Core/Behaviors/ScrollBehavior.cs +++ b/src/Blazor.Diagrams.Core/Behaviors/ScrollBehavior.cs @@ -1,19 +1,19 @@ -using Blazor.Diagrams.Core.Events; +using Blazor.Diagrams.Core.Behaviors.Base; +using Blazor.Diagrams.Core.Events; using Blazor.Diagrams.Core.Options; namespace Blazor.Diagrams.Core.Behaviors { - public class ScrollBehavior : Behavior + public class ScrollBehavior : WheelBehavior { public ScrollBehavior(Diagram diagram) : base(diagram) { - Diagram.Wheel += Diagram_Wheel; } - void Diagram_Wheel(WheelEventArgs e) + protected override void OnDiagramWheel(WheelEventArgs e) { - if (Diagram.Container == null || !Diagram.IsBehaviorEnabled(e, DiagramWheelBehavior.Scroll)) + if (Diagram.Container == null || !IsBehaviorEnabled(e)) return; var x = Diagram.Pan.X - (e.DeltaX / Diagram.Options.Zoom.ScaleFactor); @@ -21,10 +21,5 @@ void Diagram_Wheel(WheelEventArgs e) Diagram.SetPan(x, y); } - - public override void Dispose() - { - Diagram.Wheel -= Diagram_Wheel; - } } } diff --git a/src/Blazor.Diagrams.Core/Behaviors/SelectionBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/SelectionBehavior.cs index 8c3d75ab8..3c1b6c3ae 100644 --- a/src/Blazor.Diagrams.Core/Behaviors/SelectionBehavior.cs +++ b/src/Blazor.Diagrams.Core/Behaviors/SelectionBehavior.cs @@ -1,5 +1,6 @@ using Blazor.Diagrams.Core.Models.Base; using Blazor.Diagrams.Core.Events; +using Blazor.Diagrams.Core.Behaviors.Base; namespace Blazor.Diagrams.Core.Behaviors; diff --git a/src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehavior.cs index 46d699e15..3364becd3 100644 --- a/src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehavior.cs +++ b/src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehavior.cs @@ -1,16 +1,13 @@ -using Blazor.Diagrams.Core.Events; +using Blazor.Diagrams.Core.Behaviors.Base; +using Blazor.Diagrams.Core.Events; using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Core.Models.Base; -using Blazor.Diagrams.Core.Options; using System; -using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Blazor.Diagrams.Core.Behaviors { - public class SelectionBoxBehavior : Behavior + public class SelectionBoxBehavior : DragBehavior { private Point? _initialClientPoint; @@ -31,15 +28,15 @@ public override void Dispose() Diagram.PointerUp -= OnPointerUp; } - private void OnPointerDown(Model? model, PointerEventArgs e) + protected override void OnPointerDown(Model? model, PointerEventArgs e) { - if (SelectionBoundsChanged is null || model != null || !Diagram.IsBehaviorEnabled(e, DiagramDragBehavior.Select)) + if (SelectionBoundsChanged is null || model != null || !IsBehaviorEnabled(e)) return; _initialClientPoint = new Point(e.ClientX, e.ClientY); } - private void OnPointerMove(Model? model, PointerEventArgs e) + protected override void OnPointerMove(Model? model, PointerEventArgs e) { if (_initialClientPoint == null) return; @@ -73,7 +70,7 @@ void UpdateSelectionBox(MouseEventArgs e) SelectionBoundsChanged?.Invoke(this, new Rectangle(sX, sY, eX, eY)); } - private void OnPointerUp(Model? model, PointerEventArgs e) + protected override void OnPointerUp(Model? model, PointerEventArgs e) { _initialClientPoint = null; SelectionBoundsChanged?.Invoke(this, null); diff --git a/src/Blazor.Diagrams.Core/Behaviors/VirtualizationBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/VirtualizationBehavior.cs index acd4dd7b0..7d0573b06 100644 --- a/src/Blazor.Diagrams.Core/Behaviors/VirtualizationBehavior.cs +++ b/src/Blazor.Diagrams.Core/Behaviors/VirtualizationBehavior.cs @@ -1,3 +1,4 @@ +using Blazor.Diagrams.Core.Behaviors.Base; using Blazor.Diagrams.Core.Models.Base; namespace Blazor.Diagrams.Core.Behaviors; diff --git a/src/Blazor.Diagrams.Core/Behaviors/ZoomBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/ZoomBehavior.cs index 372491c4a..e8b939e51 100644 --- a/src/Blazor.Diagrams.Core/Behaviors/ZoomBehavior.cs +++ b/src/Blazor.Diagrams.Core/Behaviors/ZoomBehavior.cs @@ -1,19 +1,18 @@ -using Blazor.Diagrams.Core.Events; +using Blazor.Diagrams.Core.Behaviors.Base; +using Blazor.Diagrams.Core.Events; using System; -using Blazor.Diagrams.Core.Options; -namespace Blazor.Diagrams.Core.Behaviors; - -public class ZoomBehavior : Behavior +namespace Blazor.Diagrams.Core.Behaviors { - public ZoomBehavior(Diagram diagram) : base(diagram) + public class ZoomBehavior : WheelBehavior { - Diagram.Wheel += Diagram_Wheel; - } + public ZoomBehavior(Diagram diagram) : base(diagram) + { + } - private void Diagram_Wheel(WheelEventArgs e) + protected override void OnDiagramWheel(WheelEventArgs e) { - if (Diagram.Container == null || e.DeltaY == 0 || !Diagram.Options.Zoom.Enabled || !Diagram.IsBehaviorEnabled(e, DiagramWheelBehavior.Zoom)) + if (Diagram.Container == null || e.DeltaY == 0 || !Diagram.Options.Zoom.Enabled || !IsBehaviorEnabled(e)) return; var scale = Diagram.Options.Zoom.ScaleFactor; @@ -38,15 +37,11 @@ private void Diagram_Wheel(WheelEventArgs e) var newPanX = Diagram.Pan.X - widthDiff * xFactor; var newPanY = Diagram.Pan.Y - heightDiff * yFactor; - Diagram.Batch(() => - { - Diagram.SetPan(newPanX, newPanY); - Diagram.SetZoom(newZoom); - }); - } - - public override void Dispose() - { - Diagram.Wheel -= Diagram_Wheel; + Diagram.Batch(() => + { + Diagram.SetPan(newPanX, newPanY); + Diagram.SetZoom(newZoom); + }); + } } } diff --git a/src/Blazor.Diagrams.Core/Controls/ControlsBehavior.cs b/src/Blazor.Diagrams.Core/Controls/ControlsBehavior.cs index 05148b5e6..82f53a592 100644 --- a/src/Blazor.Diagrams.Core/Controls/ControlsBehavior.cs +++ b/src/Blazor.Diagrams.Core/Controls/ControlsBehavior.cs @@ -1,3 +1,4 @@ +using Blazor.Diagrams.Core.Behaviors.Base; using Blazor.Diagrams.Core.Events; using Blazor.Diagrams.Core.Models.Base; diff --git a/src/Blazor.Diagrams.Core/Diagram.cs b/src/Blazor.Diagrams.Core/Diagram.cs index d0527de63..22ea58cbc 100644 --- a/src/Blazor.Diagrams.Core/Diagram.cs +++ b/src/Blazor.Diagrams.Core/Diagram.cs @@ -10,6 +10,7 @@ using System.Runtime.CompilerServices; using Blazor.Diagrams.Core.Options; using Blazor.Diagrams.Core.Controls; +using Blazor.Diagrams.Core.Behaviors.Base; [assembly: InternalsVisibleTo("Blazor.Diagrams")] [assembly: InternalsVisibleTo("Blazor.Diagrams.Tests")] @@ -405,39 +406,5 @@ private void OnModelOrderChanged(Model model) public void TriggerPointerDoubleClick(Model? model, PointerEventArgs e) => PointerDoubleClick?.Invoke(model, e); #endregion - - public virtual bool IsBehaviorEnabled(PointerEventArgs e, DiagramDragBehavior behavior) - { - if (e.AltKey && !e.CtrlKey && !e.ShiftKey) - { - return behavior == Options.Behaviors.DiagramAltDragBehavior; - } - if (e.CtrlKey && !e.AltKey && !e.ShiftKey) - { - return behavior == Options.Behaviors.DiagramCtrlDragBehavior; - } - if (e.ShiftKey && !e.AltKey && !e.CtrlKey) - { - return behavior == Options.Behaviors.DiagramShiftDragBehavior; - } - return behavior == Options.Behaviors.DiagramDragBehavior; - } - - public virtual bool IsBehaviorEnabled(WheelEventArgs e, DiagramWheelBehavior behavior) - { - if (e.AltKey && !e.CtrlKey && !e.ShiftKey) - { - return behavior == Options.Behaviors.DiagramAltWheelBehavior; - } - if (e.CtrlKey && !e.AltKey && !e.ShiftKey) - { - return behavior == Options.Behaviors.DiagramCtrlWheelBehavior; - } - if (e.ShiftKey && !e.AltKey && !e.CtrlKey) - { - return behavior == Options.Behaviors.DiagramShiftWheelBehavior; - } - return behavior == Options.Behaviors.DiagramWheelBehavior; - } } } \ No newline at end of file diff --git a/src/Blazor.Diagrams.Core/Options/DiagramBehaviorOptions.cs b/src/Blazor.Diagrams.Core/Options/DiagramBehaviorOptions.cs index 027631e6b..c26c0162a 100644 --- a/src/Blazor.Diagrams.Core/Options/DiagramBehaviorOptions.cs +++ b/src/Blazor.Diagrams.Core/Options/DiagramBehaviorOptions.cs @@ -1,41 +1,75 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using Blazor.Diagrams.Core.Behaviors; +using Blazor.Diagrams.Core.Behaviors.Base; +using System; +using System.Runtime.CompilerServices; namespace Blazor.Diagrams.Core.Options { public class DiagramBehaviorOptions { - public DiagramWheelBehavior DiagramWheelBehavior { get; set; } = DiagramWheelBehavior.Zoom; + public Type? DiagramWheelBehavior + { + get => diagramWheelBehavior; + set => UpdateBehaviorOption(ref diagramWheelBehavior, value); + } + Type? diagramWheelBehavior; - public DiagramWheelBehavior DiagramAltWheelBehavior { get; set; } = DiagramWheelBehavior.Zoom; + public Type? DiagramAltWheelBehavior + { + get => diagramAltWheelBehavior; + set => UpdateBehaviorOption(ref diagramAltWheelBehavior, value); + } + Type? diagramAltWheelBehavior; - public DiagramWheelBehavior DiagramCtrlWheelBehavior { get; set; } = DiagramWheelBehavior.Zoom; + public Type? DiagramCtrlWheelBehavior + { + get => diagramCtrlWheelBehavior; + set => UpdateBehaviorOption(ref diagramCtrlWheelBehavior, value); + } + Type? diagramCtrlWheelBehavior; - public DiagramWheelBehavior DiagramShiftWheelBehavior { get; set; } = DiagramWheelBehavior.Zoom; + public Type? DiagramShiftWheelBehavior + { + get => diagramShiftWheelBehavior; + set => UpdateBehaviorOption(ref diagramShiftWheelBehavior, value); + } + Type? diagramShiftWheelBehavior; - public DiagramDragBehavior DiagramDragBehavior { get; set; } = DiagramDragBehavior.Pan; + public Type? DiagramDragBehavior + { + get => diagramDragBehavior; + set => UpdateBehaviorOption(ref diagramDragBehavior, value); + } + Type? diagramDragBehavior; - public DiagramDragBehavior DiagramAltDragBehavior { get; set; } = DiagramDragBehavior.Pan; + public Type? DiagramAltDragBehavior + { + get => diagramAltDragBehavior; + set => UpdateBehaviorOption(ref diagramAltDragBehavior, value); + } + Type? diagramAltDragBehavior; - public DiagramDragBehavior DiagramCtrlDragBehavior { get; set; } = DiagramDragBehavior.Pan; + public Type? DiagramCtrlDragBehavior + { + get => diagramCtrlDragBehavior; + set => UpdateBehaviorOption(ref diagramCtrlDragBehavior, value); + } + Type? diagramCtrlDragBehavior; - public DiagramDragBehavior DiagramShiftDragBehavior { get; set; } = DiagramDragBehavior.Select; - } + public Type? DiagramShiftDragBehavior + { + get => diagramShiftDragBehavior; + set => UpdateBehaviorOption(ref diagramShiftDragBehavior, value); + } + Type? diagramShiftDragBehavior; - public enum DiagramWheelBehavior - { - None, - Zoom, - Scroll, - } - - public enum DiagramDragBehavior - { - None, - Pan, - Select, + void UpdateBehaviorOption(ref Type? property, Type? value, [CallerMemberName] string propertyName = "") where T : Behavior + { + if (value is not null && !value.IsSubclassOf(typeof(T))) + { + throw new InvalidOperationException($"{propertyName} must be a type of {typeof(T).Name}"); + } + property = value; + } } } diff --git a/src/Blazor.Diagrams.Core/Options/DiagramOptions.cs b/src/Blazor.Diagrams.Core/Options/DiagramOptions.cs index ab1739211..7854cf1b0 100644 --- a/src/Blazor.Diagrams.Core/Options/DiagramOptions.cs +++ b/src/Blazor.Diagrams.Core/Options/DiagramOptions.cs @@ -1,3 +1,5 @@ +using Blazor.Diagrams.Core.Behaviors; + namespace Blazor.Diagrams.Core.Options; public class DiagramOptions @@ -12,5 +14,10 @@ public class DiagramOptions public virtual DiagramGroupOptions Groups { get; } = new(); public virtual DiagramConstraintsOptions Constraints { get; } = new(); public virtual DiagramVirtualizationOptions Virtualization { get; } = new(); - public virtual DiagramBehaviorOptions Behaviors { get; } = new(); + public virtual DiagramBehaviorOptions Behaviors { get; } = new() + { + DiagramDragBehavior = typeof(PanBehavior), + DiagramShiftDragBehavior = typeof(SelectionBoxBehavior), + DiagramWheelBehavior = typeof(ZoomBehavior), + }; } \ No newline at end of file diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviorTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviorTests.cs index 8ad20abb5..0bdfe97e1 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviorTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviorTests.cs @@ -1,7 +1,6 @@ -using Blazor.Diagrams.Core.Events; +using Blazor.Diagrams.Core.Behaviors; +using Blazor.Diagrams.Core.Events; using Blazor.Diagrams.Core.Geometry; -using Blazor.Diagrams.Core.Options; -using Moq; using Xunit; namespace Blazor.Diagrams.Core.Tests.Behaviors @@ -12,46 +11,44 @@ public class PanBehaviorTests public void Behavior_WhenBehaviorEnabled_ShouldPan() { // Arrange - var diagram = new Mock(null) { CallBase = true }; - diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())) - .Returns((PointerEventArgs _, DiagramDragBehavior behaviour) => behaviour == DiagramDragBehavior.Pan); - diagram.Object.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); + var diagram = new TestDiagram(); + diagram.Options.Behaviors.DiagramDragBehavior = typeof(PanBehavior); + diagram.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); - Assert.Equal(0, diagram.Object.Pan.X); - Assert.Equal(0, diagram.Object.Pan.Y); + Assert.Equal(0, diagram.Pan.X); + Assert.Equal(0, diagram.Pan.Y); // Act - diagram.Object.TriggerPointerDown(null, + diagram.TriggerPointerDown(null, new PointerEventArgs(100, 100, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); - diagram.Object.TriggerPointerMove(null, + diagram.TriggerPointerMove(null, new PointerEventArgs(200, 200, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); // Assert - Assert.Equal(100, diagram.Object.Pan.X); - Assert.Equal(100, diagram.Object.Pan.Y); + Assert.Equal(100, diagram.Pan.X); + Assert.Equal(100, diagram.Pan.Y); } [Fact] public void Behavior_WhenBehaviorDisabled_ShouldNotPan() { // Arrange - var diagram = new Mock(null) { CallBase = true }; - diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())) - .Returns(false); - diagram.Object.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); + var diagram = new TestDiagram(); + diagram.Options.Behaviors.DiagramDragBehavior = null; + diagram.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); - Assert.Equal(0, diagram.Object.Pan.X); - Assert.Equal(0, diagram.Object.Pan.Y); + Assert.Equal(0, diagram.Pan.X); + Assert.Equal(0, diagram.Pan.Y); // Act - diagram.Object.TriggerPointerDown(null, + diagram.TriggerPointerDown(null, new PointerEventArgs(100, 100, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); - diagram.Object.TriggerPointerMove(null, + diagram.TriggerPointerMove(null, new PointerEventArgs(200, 200, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); // Assert - Assert.Equal(0, diagram.Object.Pan.X); - Assert.Equal(0, diagram.Object.Pan.Y); + Assert.Equal(0, diagram.Pan.X); + Assert.Equal(0, diagram.Pan.Y); } } } diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviorTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviorTests.cs index c3b0eaf17..f4fc2163c 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviorTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviorTests.cs @@ -1,7 +1,6 @@ -using Blazor.Diagrams.Core.Events; +using Blazor.Diagrams.Core.Behaviors; +using Blazor.Diagrams.Core.Events; using Blazor.Diagrams.Core.Geometry; -using Blazor.Diagrams.Core.Options; -using Moq; using Xunit; namespace Blazor.Diagrams.Core.Tests.Behaviors @@ -12,35 +11,33 @@ public class ScrollBehaviorTests public void Behavior_WhenBehaviorEnabled_ShouldScroll() { // Arrange - var diagram = new Mock(null) { CallBase = true }; - diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())) - .Returns((WheelEventArgs _, DiagramWheelBehavior behaviour) => behaviour == DiagramWheelBehavior.Scroll); - diagram.Object.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); - diagram.Object.Options.Zoom.ScaleFactor = 1.05; + var diagram = new TestDiagram(); + diagram.Options.Behaviors.DiagramWheelBehavior = typeof(ScrollBehavior); + diagram.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); + diagram.Options.Zoom.ScaleFactor = 1.05; // Act - diagram.Object.TriggerWheel(new WheelEventArgs(100, 100, 0, 0, false, false, false, 100, 200, 0, 0)); + diagram.TriggerWheel(new WheelEventArgs(100, 100, 0, 0, false, false, false, 100, 200, 0, 0)); // Assert - Assert.Equal(-95, diagram.Object.Pan.X, 0); - Assert.Equal(-190, diagram.Object.Pan.Y, 0); + Assert.Equal(-95, diagram.Pan.X, 0); + Assert.Equal(-190, diagram.Pan.Y, 0); } [Fact] public void Behavior_WhenBehaviorDisabled_ShouldNotScroll() { // Arrange - var diagram = new Mock(null) { CallBase = true }; - diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())) - .Returns(false); - diagram.Object.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); + var diagram = new TestDiagram(); + diagram.Options.Behaviors.DiagramWheelBehavior = null; + diagram.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); // Act - diagram.Object.TriggerWheel(new WheelEventArgs(100, 100, 0, 0, false, false, false, 100, 200, 0, 0)); + diagram.TriggerWheel(new WheelEventArgs(100, 100, 0, 0, false, false, false, 100, 200, 0, 0)); // Assert - Assert.Equal(0, diagram.Object.Pan.X); - Assert.Equal(0, diagram.Object.Pan.Y); + Assert.Equal(0, diagram.Pan.X); + Assert.Equal(0, diagram.Pan.Y); } } } diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs index 4a93c8c7e..b63cff519 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs @@ -2,8 +2,6 @@ using Blazor.Diagrams.Core.Events; using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Core.Models; -using Blazor.Diagrams.Core.Options; -using Moq; using Xunit; namespace Blazor.Diagrams.Core.Tests.Behaviors @@ -14,12 +12,11 @@ public class SelectionBoxBehaviorTests public void Behavior_WhenBehaviorEnabled_ShouldUpdateSelectionBounds() { // Arrange - var diagram = new Mock(null) { CallBase = true }; - diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())) - .Returns((PointerEventArgs _, DiagramDragBehavior behaviour) => behaviour == DiagramDragBehavior.Select); - diagram.Object.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); + var diagram = new TestDiagram(); + diagram.Options.Behaviors.DiagramDragBehavior = typeof(SelectionBoxBehavior); + diagram.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); - var selectionBoxBehavior = diagram.Object.GetBehavior()!; + var selectionBoxBehavior = diagram.GetBehavior()!; bool boundsChangedEventInvoked = false; Rectangle? lastBounds = null; selectionBoxBehavior.SelectionBoundsChanged += (_, newBounds) => @@ -29,9 +26,9 @@ public void Behavior_WhenBehaviorEnabled_ShouldUpdateSelectionBounds() }; // Act - diagram.Object.TriggerPointerDown(null, + diagram.TriggerPointerDown(null, new PointerEventArgs(100, 100, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); - diagram.Object.TriggerPointerMove(null, + diagram.TriggerPointerMove(null, new PointerEventArgs(200, 150, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); // Assert @@ -46,12 +43,11 @@ public void Behavior_WhenBehaviorEnabled_ShouldUpdateSelectionBounds() public void Behavior_WhenBehaviorDisabled_ShouldNotUpdateSelectionBounds() { // Arrange - var diagram = new Mock(null) { CallBase = true }; - diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())) - .Returns(false); - diagram.Object.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); + var diagram = new TestDiagram(); + diagram.Options.Behaviors.DiagramDragBehavior = null; + diagram.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); - var selectionBoxBehavior = diagram.Object.GetBehavior()!; + var selectionBoxBehavior = diagram.GetBehavior()!; bool boundsChangedEventInvoked = false; Rectangle? lastBounds = null; selectionBoxBehavior.SelectionBoundsChanged += (_, newBounds) => @@ -61,9 +57,9 @@ public void Behavior_WhenBehaviorDisabled_ShouldNotUpdateSelectionBounds() }; // Act - diagram.Object.TriggerPointerDown(null, + diagram.TriggerPointerDown(null, new PointerEventArgs(100, 100, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); - diagram.Object.TriggerPointerMove(null, + diagram.TriggerPointerMove(null, new PointerEventArgs(200, 150, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); // Assert @@ -75,12 +71,11 @@ public void Behavior_WhenBehaviorDisabled_ShouldNotUpdateSelectionBounds() public void Behavior_WithBoundsChangedDelegate_ShouldSelectNodesInsideArea() { // Arrange - var diagram = new Mock(null) { CallBase = true }; - diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())) - .Returns((PointerEventArgs _, DiagramDragBehavior behaviour) => behaviour == DiagramDragBehavior.Select); - diagram.Object.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); + var diagram = new TestDiagram(); + diagram.Options.Behaviors.DiagramDragBehavior = typeof(SelectionBoxBehavior); + diagram.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); - var selectionBoxBehavior = diagram.Object.GetBehavior()!; + var selectionBoxBehavior = diagram.GetBehavior()!; selectionBoxBehavior.SelectionBoundsChanged += (_, _) => { }; var node = new NodeModel() @@ -88,18 +83,18 @@ public void Behavior_WithBoundsChangedDelegate_ShouldSelectNodesInsideArea() Size = new Size(100, 100), Position = new Point(150, 150) }; - diagram.Object.Nodes.Add(node); + diagram.Nodes.Add(node); // Act - diagram.Object.TriggerPointerDown(null, + diagram.TriggerPointerDown(null, new PointerEventArgs(100, 100, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); - diagram.Object.TriggerPointerMove(null, + diagram.TriggerPointerMove(null, new PointerEventArgs(300, 300, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); // Assert Assert.True(node.Selected); - diagram.Object.TriggerPointerMove(null, + diagram.TriggerPointerMove(null, new PointerEventArgs(100, 100, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); Assert.False(node.Selected); } @@ -108,28 +103,27 @@ public void Behavior_WithBoundsChangedDelegate_ShouldSelectNodesInsideArea() public void Behavior_WithoutBoundsChangedDelegate_ShouldNotSelectNodesInsideArea() { // Arrange - var diagram = new Mock(null) { CallBase = true }; - diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())) - .Returns((PointerEventArgs _, DiagramDragBehavior behaviour) => behaviour == DiagramDragBehavior.Select); - diagram.Object.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); + var diagram = new TestDiagram(); + diagram.Options.Behaviors.DiagramDragBehavior = typeof(SelectionBoxBehavior); + 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.Object.Nodes.Add(node); + diagram.Nodes.Add(node); // Act - diagram.Object.TriggerPointerDown(null, + diagram.TriggerPointerDown(null, new PointerEventArgs(100, 100, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); - diagram.Object.TriggerPointerMove(null, + diagram.TriggerPointerMove(null, new PointerEventArgs(300, 300, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); // Assert Assert.False(node.Selected); - diagram.Object.TriggerPointerMove(null, + diagram.TriggerPointerMove(null, new PointerEventArgs(100, 100, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); Assert.False(node.Selected); } diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviorTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviorTests.cs index 6086ba3f3..89cf5ef2d 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviorTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviorTests.cs @@ -1,7 +1,6 @@ -using Blazor.Diagrams.Core.Events; +using Blazor.Diagrams.Core.Behaviors; +using Blazor.Diagrams.Core.Events; using Blazor.Diagrams.Core.Geometry; -using Blazor.Diagrams.Core.Options; -using Moq; using Xunit; namespace Blazor.Diagrams.Core.Tests.Behaviors @@ -12,32 +11,30 @@ public class ZoomBehaviorTests public void Behavior_WhenBehaviorEnabled_ShouldZoom() { // Arrange - var diagram = new Mock(null) { CallBase = true }; - diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())) - .Returns((WheelEventArgs _, DiagramWheelBehavior behaviour) => behaviour == DiagramWheelBehavior.Zoom); - diagram.Object.SetContainer(new Rectangle(0, 0, 100, 100)); + var diagram = new TestDiagram(); + diagram.Options.Behaviors.DiagramWheelBehavior = typeof(ZoomBehavior); + diagram.SetContainer(new Rectangle(0, 0, 100, 100)); // Act - diagram.Object.TriggerWheel(new WheelEventArgs(100, 100, 0, 0, false, false, false, 0, 100, 0, 0)); + diagram.TriggerWheel(new WheelEventArgs(100, 100, 0, 0, false, false, false, 0, 100, 0, 0)); // Assert - Assert.Equal(1.05, diagram.Object.Zoom); + Assert.Equal(1.05, diagram.Zoom); } [Fact] public void Behavior_WhenBehaviorDisabled_ShouldNotZoom() { // Arrange - var diagram = new Mock(null) { CallBase = true }; - diagram.Setup(d => d.IsBehaviorEnabled(It.IsAny(), It.IsAny())) - .Returns(false); - diagram.Object.SetContainer(new Rectangle(0, 0, 100, 100)); + var diagram = new TestDiagram(); + diagram.Options.Behaviors.DiagramWheelBehavior = null; + diagram.SetContainer(new Rectangle(0, 0, 100, 100)); // Act - diagram.Object.TriggerWheel(new WheelEventArgs(100, 100, 0, 0, false, false, false, 0, 100, 0, 0)); + diagram.TriggerWheel(new WheelEventArgs(100, 100, 0, 0, false, false, false, 0, 100, 0, 0)); // Assert - Assert.Equal(1, diagram.Object.Zoom); + Assert.Equal(1, diagram.Zoom); } } } diff --git a/tests/Blazor.Diagrams.Core.Tests/Options/DiagramBehaviorOptionsTests.cs b/tests/Blazor.Diagrams.Core.Tests/Options/DiagramBehaviorOptionsTests.cs index ccc174c4e..188e9e267 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Options/DiagramBehaviorOptionsTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Options/DiagramBehaviorOptionsTests.cs @@ -1,4 +1,5 @@ -using Blazor.Diagrams.Core.Events; +using Blazor.Diagrams.Core.Behaviors; +using Blazor.Diagrams.Core.Events; using Blazor.Diagrams.Core.Options; using System; using System.Collections.Generic; @@ -12,91 +13,115 @@ namespace Blazor.Diagrams.Core.Tests.Options public class DiagramBehaviorOptionsTests { [Fact] - public void DiagramBehaviorOptions_DragBehavior_IsEnabled() + public void DiagramBehaviorOptions_DragBehavior_IsBehaviorEnabled() { var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramDragBehavior = DiagramDragBehavior.None; - Assert.False(diagram.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true), DiagramDragBehavior.Pan)); + diagram.Options.Behaviors.DiagramDragBehavior = null; + Assert.False(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true))); - diagram.Options.Behaviors.DiagramDragBehavior = DiagramDragBehavior.Pan; - Assert.True(diagram.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true), DiagramDragBehavior.Pan)); + diagram.Options.Behaviors.DiagramDragBehavior = typeof(PanBehavior); + Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true))); } [Fact] - public void DiagramBehaviorOptions_AltDragBehavior_IsEnabled() + public void DiagramBehaviorOptions_AltDragBehavior_IsBehaviorEnabled() { var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramAltDragBehavior = DiagramDragBehavior.None; - Assert.False(diagram.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, false, true, 0, 0, 0, 0, 0, 0, string.Empty, true), DiagramDragBehavior.Pan)); + diagram.Options.Behaviors.DiagramDragBehavior = typeof(PanBehavior); + diagram.Options.Behaviors.DiagramAltDragBehavior = null; + Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, false, true, 0, 0, 0, 0, 0, 0, string.Empty, true))); - diagram.Options.Behaviors.DiagramAltDragBehavior = DiagramDragBehavior.Pan; - Assert.True(diagram.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, false, true, 0, 0, 0, 0, 0, 0, string.Empty, true), DiagramDragBehavior.Pan)); + diagram.Options.Behaviors.DiagramDragBehavior = null; + Assert.False(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, false, true, 0, 0, 0, 0, 0, 0, string.Empty, true))); + + diagram.Options.Behaviors.DiagramAltDragBehavior = typeof(PanBehavior); + Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, false, true, 0, 0, 0, 0, 0, 0, string.Empty, true))); } [Fact] - public void DiagramBehaviorOptions_CtrlDragBehavior_IsEnabled() + public void DiagramBehaviorOptions_CtrlDragBehavior_IsBehaviorEnabled() { var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramCtrlDragBehavior = DiagramDragBehavior.None; - Assert.False(diagram.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, true, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true), DiagramDragBehavior.Pan)); + diagram.Options.Behaviors.DiagramDragBehavior = typeof(PanBehavior); + diagram.Options.Behaviors.DiagramCtrlDragBehavior = null; + Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, true, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true))); + + diagram.Options.Behaviors.DiagramDragBehavior = null; + Assert.False(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, true, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true))); - diagram.Options.Behaviors.DiagramCtrlDragBehavior = DiagramDragBehavior.Pan; - Assert.True(diagram.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, true, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true), DiagramDragBehavior.Pan)); + diagram.Options.Behaviors.DiagramCtrlDragBehavior = typeof(PanBehavior); + Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, true, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true))); } [Fact] - public void DiagramBehaviorOptions_ShiftDragBehavior_IsEnabled() + public void DiagramBehaviorOptions_ShiftDragBehavior_IsBehaviorEnabled() { var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramShiftDragBehavior = DiagramDragBehavior.None; - Assert.False(diagram.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, true, false, 0, 0, 0, 0, 0, 0, string.Empty, true), DiagramDragBehavior.Pan)); + diagram.Options.Behaviors.DiagramDragBehavior = typeof(PanBehavior); + diagram.Options.Behaviors.DiagramShiftDragBehavior = null; + Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, true, false, 0, 0, 0, 0, 0, 0, string.Empty, true))); + + diagram.Options.Behaviors.DiagramDragBehavior = null; + Assert.False(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, true, false, 0, 0, 0, 0, 0, 0, string.Empty, true))); - diagram.Options.Behaviors.DiagramShiftDragBehavior = DiagramDragBehavior.Pan; - Assert.True(diagram.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, true, false, 0, 0, 0, 0, 0, 0, string.Empty, true), DiagramDragBehavior.Pan)); + diagram.Options.Behaviors.DiagramShiftDragBehavior = typeof(PanBehavior); + Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, true, false, 0, 0, 0, 0, 0, 0, string.Empty, true))); } [Fact] - public void DiagramBehaviorOptions_DefaultScrollBehavior_IsEnabled() + public void DiagramBehaviorOptions_DefaultScrollBehavior_IsBehaviorEnabled() { var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramWheelBehavior = DiagramWheelBehavior.None; - Assert.False(diagram.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, false, false, 0, 0, 0, 0), DiagramWheelBehavior.Zoom)); + diagram.Options.Behaviors.DiagramWheelBehavior = null; + Assert.False(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, false, false, 0, 0, 0, 0))); - diagram.Options.Behaviors.DiagramWheelBehavior = DiagramWheelBehavior.Zoom; - Assert.True(diagram.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, false, false, 0, 0, 0, 0), DiagramWheelBehavior.Zoom)); + diagram.Options.Behaviors.DiagramWheelBehavior = typeof(ZoomBehavior); + Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, false, false, 0, 0, 0, 0))); } [Fact] - public void DiagramBehaviorOptions_AltScrollBehavior_IsEnabled() + public void DiagramBehaviorOptions_AltScrollBehavior_IsBehaviorEnabled() { var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramAltWheelBehavior = DiagramWheelBehavior.None; - Assert.False(diagram.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, false, true, 0, 0, 0, 0), DiagramWheelBehavior.Zoom)); + diagram.Options.Behaviors.DiagramWheelBehavior = typeof(ZoomBehavior); + diagram.Options.Behaviors.DiagramAltWheelBehavior = null; + Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, false, true, 0, 0, 0, 0))); - diagram.Options.Behaviors.DiagramAltWheelBehavior = DiagramWheelBehavior.Zoom; - Assert.True(diagram.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, false, true, 0, 0, 0, 0), DiagramWheelBehavior.Zoom)); + diagram.Options.Behaviors.DiagramWheelBehavior = null; + Assert.False(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, false, true, 0, 0, 0, 0))); + + diagram.Options.Behaviors.DiagramAltWheelBehavior = typeof(ZoomBehavior); + Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, false, true, 0, 0, 0, 0))); } [Fact] - public void DiagramBehaviorOptions_CtrlScrollBehavior_IsEnabled() + public void DiagramBehaviorOptions_CtrlScrollBehavior_IsBehaviorEnabled() { var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramCtrlWheelBehavior = DiagramWheelBehavior.None; - Assert.False(diagram.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, true, false, false, 0, 0, 0, 0), DiagramWheelBehavior.Zoom)); + diagram.Options.Behaviors.DiagramWheelBehavior = typeof(ZoomBehavior); + diagram.Options.Behaviors.DiagramCtrlWheelBehavior = null; + Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, true, false, false, 0, 0, 0, 0))); + + diagram.Options.Behaviors.DiagramWheelBehavior = null; + Assert.False(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, true, false, false, 0, 0, 0, 0))); - diagram.Options.Behaviors.DiagramCtrlWheelBehavior = DiagramWheelBehavior.Zoom; - Assert.True(diagram.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, true, false, false, 0, 0, 0, 0), DiagramWheelBehavior.Zoom)); + diagram.Options.Behaviors.DiagramCtrlWheelBehavior = typeof(ZoomBehavior); + Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, true, false, false, 0, 0, 0, 0))); } [Fact] - public void DiagramBehaviorOptions_ShiftScrollBehavior_IsEnabled() + public void DiagramBehaviorOptions_ShiftScrollBehavior_IsBehaviorEnabled() { var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramShiftWheelBehavior = DiagramWheelBehavior.None; - Assert.False(diagram.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, true, false, 0, 0, 0, 0), DiagramWheelBehavior.Zoom)); + diagram.Options.Behaviors.DiagramWheelBehavior = typeof(ZoomBehavior); + diagram.Options.Behaviors.DiagramShiftWheelBehavior = null; + Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, true, false, 0, 0, 0, 0))); + + diagram.Options.Behaviors.DiagramWheelBehavior = null; + Assert.False(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, true, false, 0, 0, 0, 0))); - diagram.Options.Behaviors.DiagramShiftWheelBehavior = DiagramWheelBehavior.Zoom; - Assert.True(diagram.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, true, false, 0, 0, 0, 0), DiagramWheelBehavior.Zoom)); + diagram.Options.Behaviors.DiagramShiftWheelBehavior = typeof(ZoomBehavior); + Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, true, false, 0, 0, 0, 0))); } } } diff --git a/tests/Blazor.Diagrams.Tests/Components/Widgets/SelectionBoxWidgetTests.cs b/tests/Blazor.Diagrams.Tests/Components/Widgets/SelectionBoxWidgetTests.cs index d1f3b686c..d43368f0e 100644 --- a/tests/Blazor.Diagrams.Tests/Components/Widgets/SelectionBoxWidgetTests.cs +++ b/tests/Blazor.Diagrams.Tests/Components/Widgets/SelectionBoxWidgetTests.cs @@ -1,22 +1,10 @@ -using Blazor.Diagrams.Components.Renderers; -using Blazor.Diagrams.Components; -using Blazor.Diagrams.Core.Models; -using Bunit; -using Moq; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using Bunit; using Xunit; using Blazor.Diagrams.Components.Widgets; -using AngleSharp.Dom; using AngleSharp.Css.Dom; -using Blazor.Diagrams.Options; -using Blazor.Diagrams.Core.Options; -using Blazor.Diagrams.Core; using Blazor.Diagrams.Core.Events; using Blazor.Diagrams.Core.Geometry; +using Blazor.Diagrams.Core.Behaviors; namespace Blazor.Diagrams.Tests.Components.Widgets { @@ -28,7 +16,7 @@ public void SelectionBoxWidget_SelectionBoundsChanged_RendersSelectionBoxWidgetI // Arrange using var ctx = new TestContext(); var diagram = new BlazorDiagram(); - diagram.Options.Behaviors.DiagramDragBehavior = DiagramDragBehavior.Select; + diagram.Options.Behaviors.DiagramDragBehavior = typeof(SelectionBoxBehavior); diagram.SetPan(-75, -100); diagram.SetContainer(new Rectangle(new Point(0, 0), new Size(500, 500))); From 976c1a6ff1811ed477d54d0c375a350ada1708df Mon Sep 17 00:00:00 2001 From: Matt Swain Date: Wed, 24 May 2023 11:20:18 +1000 Subject: [PATCH 08/17] refactored to not use types --- .../Behaviors/Base/DragBehavior.cs | 10 ++- .../Behaviors/Base/WheelBehavior.cs | 9 ++- .../Options/DiagramBehaviorOptions.cs | 65 +++---------------- .../Options/DiagramOptions.cs | 7 +- src/Blazor.Diagrams/BlazorDiagram.cs | 4 ++ .../Behaviors/PanBehaviorTests.cs | 2 +- .../Behaviors/ScrollBehaviorTests.cs | 2 +- .../Behaviors/SelectionBoxBehaviorTests.cs | 6 +- .../Behaviors/ZoomBehaviorTests.cs | 2 +- .../Options/DiagramBehaviorOptionsTests.cs | 28 ++++---- .../Widgets/SelectionBoxWidgetTests.cs | 2 +- 11 files changed, 42 insertions(+), 95 deletions(-) diff --git a/src/Blazor.Diagrams.Core/Behaviors/Base/DragBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/Base/DragBehavior.cs index bb42fdeff..0c11b180d 100644 --- a/src/Blazor.Diagrams.Core/Behaviors/Base/DragBehavior.cs +++ b/src/Blazor.Diagrams.Core/Behaviors/Base/DragBehavior.cs @@ -21,24 +21,22 @@ public DragBehavior(Diagram diagram) public virtual bool IsBehaviorEnabled(PointerEventArgs e) { - var dragBehavior = Diagram.Options.Behaviors.DiagramDragBehavior; if (e.AltKey && !e.CtrlKey && !e.ShiftKey && Diagram.Options.Behaviors.DiagramAltDragBehavior is not null) { - dragBehavior = Diagram.Options.Behaviors.DiagramAltDragBehavior; + return this == Diagram.Options.Behaviors.DiagramAltDragBehavior; } else if (!e.AltKey && e.CtrlKey && !e.ShiftKey && Diagram.Options.Behaviors.DiagramCtrlDragBehavior is not null) { - dragBehavior = Diagram.Options.Behaviors.DiagramCtrlDragBehavior; + return this == Diagram.Options.Behaviors.DiagramCtrlDragBehavior; } else if (!e.AltKey && !e.CtrlKey && e.ShiftKey && Diagram.Options.Behaviors.DiagramShiftDragBehavior is not null) { - dragBehavior = Diagram.Options.Behaviors.DiagramShiftDragBehavior; + return this == Diagram.Options.Behaviors.DiagramShiftDragBehavior; } - - return dragBehavior?.IsAssignableFrom(GetType()) ?? false; + return this == Diagram.Options.Behaviors.DiagramDragBehavior; } public override void Dispose() diff --git a/src/Blazor.Diagrams.Core/Behaviors/Base/WheelBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/Base/WheelBehavior.cs index 31ec39814..cbaba03b2 100644 --- a/src/Blazor.Diagrams.Core/Behaviors/Base/WheelBehavior.cs +++ b/src/Blazor.Diagrams.Core/Behaviors/Base/WheelBehavior.cs @@ -15,24 +15,23 @@ protected WheelBehavior(Diagram diagram) public virtual bool IsBehaviorEnabled(WheelEventArgs e) { - var wheelBehavior = Diagram.Options.Behaviors.DiagramWheelBehavior; if (e.AltKey && !e.CtrlKey && !e.ShiftKey && Diagram.Options.Behaviors.DiagramAltWheelBehavior is not null) { - wheelBehavior = Diagram.Options.Behaviors.DiagramAltWheelBehavior; + return this == Diagram.Options.Behaviors.DiagramAltWheelBehavior; } else if (!e.AltKey && e.CtrlKey && !e.ShiftKey && Diagram.Options.Behaviors.DiagramCtrlWheelBehavior is not null) { - wheelBehavior = Diagram.Options.Behaviors.DiagramCtrlWheelBehavior; + return this == Diagram.Options.Behaviors.DiagramCtrlWheelBehavior; } else if (!e.AltKey && !e.CtrlKey && e.ShiftKey && Diagram.Options.Behaviors.DiagramShiftWheelBehavior is not null) { - wheelBehavior = Diagram.Options.Behaviors.DiagramShiftWheelBehavior; + return this == Diagram.Options.Behaviors.DiagramShiftWheelBehavior; } - return wheelBehavior?.IsAssignableFrom(GetType()) ?? false; + return this == Diagram.Options.Behaviors.DiagramWheelBehavior; } public override void Dispose() diff --git a/src/Blazor.Diagrams.Core/Options/DiagramBehaviorOptions.cs b/src/Blazor.Diagrams.Core/Options/DiagramBehaviorOptions.cs index c26c0162a..a0b7b0aa7 100644 --- a/src/Blazor.Diagrams.Core/Options/DiagramBehaviorOptions.cs +++ b/src/Blazor.Diagrams.Core/Options/DiagramBehaviorOptions.cs @@ -7,69 +7,20 @@ namespace Blazor.Diagrams.Core.Options { public class DiagramBehaviorOptions { - public Type? DiagramWheelBehavior - { - get => diagramWheelBehavior; - set => UpdateBehaviorOption(ref diagramWheelBehavior, value); - } - Type? diagramWheelBehavior; + public WheelBehavior? DiagramWheelBehavior { get; set; } - public Type? DiagramAltWheelBehavior - { - get => diagramAltWheelBehavior; - set => UpdateBehaviorOption(ref diagramAltWheelBehavior, value); - } - Type? diagramAltWheelBehavior; + public WheelBehavior? DiagramAltWheelBehavior { get; set; } - public Type? DiagramCtrlWheelBehavior - { - get => diagramCtrlWheelBehavior; - set => UpdateBehaviorOption(ref diagramCtrlWheelBehavior, value); - } - Type? diagramCtrlWheelBehavior; + public WheelBehavior? DiagramCtrlWheelBehavior { get; set; } - public Type? DiagramShiftWheelBehavior - { - get => diagramShiftWheelBehavior; - set => UpdateBehaviorOption(ref diagramShiftWheelBehavior, value); - } - Type? diagramShiftWheelBehavior; + public WheelBehavior? DiagramShiftWheelBehavior { get; set; } - public Type? DiagramDragBehavior - { - get => diagramDragBehavior; - set => UpdateBehaviorOption(ref diagramDragBehavior, value); - } - Type? diagramDragBehavior; + public DragBehavior? DiagramDragBehavior { get; set; } - public Type? DiagramAltDragBehavior - { - get => diagramAltDragBehavior; - set => UpdateBehaviorOption(ref diagramAltDragBehavior, value); - } - Type? diagramAltDragBehavior; + public DragBehavior? DiagramAltDragBehavior { get; set; } - public Type? DiagramCtrlDragBehavior - { - get => diagramCtrlDragBehavior; - set => UpdateBehaviorOption(ref diagramCtrlDragBehavior, value); - } - Type? diagramCtrlDragBehavior; + public DragBehavior? DiagramCtrlDragBehavior { get; set; } - public Type? DiagramShiftDragBehavior - { - get => diagramShiftDragBehavior; - set => UpdateBehaviorOption(ref diagramShiftDragBehavior, value); - } - Type? diagramShiftDragBehavior; - - void UpdateBehaviorOption(ref Type? property, Type? value, [CallerMemberName] string propertyName = "") where T : Behavior - { - if (value is not null && !value.IsSubclassOf(typeof(T))) - { - throw new InvalidOperationException($"{propertyName} must be a type of {typeof(T).Name}"); - } - property = value; - } + public DragBehavior? DiagramShiftDragBehavior { get; set; } } } diff --git a/src/Blazor.Diagrams.Core/Options/DiagramOptions.cs b/src/Blazor.Diagrams.Core/Options/DiagramOptions.cs index 7854cf1b0..5dc985adb 100644 --- a/src/Blazor.Diagrams.Core/Options/DiagramOptions.cs +++ b/src/Blazor.Diagrams.Core/Options/DiagramOptions.cs @@ -14,10 +14,5 @@ public class DiagramOptions public virtual DiagramGroupOptions Groups { get; } = new(); public virtual DiagramConstraintsOptions Constraints { get; } = new(); public virtual DiagramVirtualizationOptions Virtualization { get; } = new(); - public virtual DiagramBehaviorOptions Behaviors { get; } = new() - { - DiagramDragBehavior = typeof(PanBehavior), - DiagramShiftDragBehavior = typeof(SelectionBoxBehavior), - DiagramWheelBehavior = typeof(ZoomBehavior), - }; + public virtual DiagramBehaviorOptions Behaviors { get; } = new(); } \ No newline at end of file diff --git a/src/Blazor.Diagrams/BlazorDiagram.cs b/src/Blazor.Diagrams/BlazorDiagram.cs index ab61d98a8..65e6ef6d3 100644 --- a/src/Blazor.Diagrams/BlazorDiagram.cs +++ b/src/Blazor.Diagrams/BlazorDiagram.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using Blazor.Diagrams.Components.Controls; using Blazor.Diagrams.Core; +using Blazor.Diagrams.Core.Behaviors; using Blazor.Diagrams.Core.Controls.Default; using Blazor.Diagrams.Core.Models.Base; using Blazor.Diagrams.Options; @@ -23,6 +24,9 @@ public BlazorDiagram(BlazorDiagramOptions? options = null) }; Options = options ?? new BlazorDiagramOptions(); + Options.Behaviors.DiagramDragBehavior ??= GetBehavior(); + Options.Behaviors.DiagramShiftDragBehavior ??= GetBehavior(); + Options.Behaviors.DiagramWheelBehavior ??= GetBehavior(); } public override BlazorDiagramOptions Options { get; } diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviorTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviorTests.cs index 0bdfe97e1..da2fa3368 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviorTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviorTests.cs @@ -12,7 +12,7 @@ public void Behavior_WhenBehaviorEnabled_ShouldPan() { // Arrange var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramDragBehavior = typeof(PanBehavior); + diagram.Options.Behaviors.DiagramDragBehavior = diagram.GetBehavior(); diagram.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); Assert.Equal(0, diagram.Pan.X); diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviorTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviorTests.cs index f4fc2163c..556a7a26c 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviorTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviorTests.cs @@ -12,7 +12,7 @@ public void Behavior_WhenBehaviorEnabled_ShouldScroll() { // Arrange var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramWheelBehavior = typeof(ScrollBehavior); + diagram.Options.Behaviors.DiagramWheelBehavior = diagram.GetBehavior(); diagram.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); diagram.Options.Zoom.ScaleFactor = 1.05; diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs index b63cff519..2f9f90e32 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs @@ -13,7 +13,7 @@ public void Behavior_WhenBehaviorEnabled_ShouldUpdateSelectionBounds() { // Arrange var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramDragBehavior = typeof(SelectionBoxBehavior); + diagram.Options.Behaviors.DiagramDragBehavior = diagram.GetBehavior(); diagram.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); var selectionBoxBehavior = diagram.GetBehavior()!; @@ -72,7 +72,7 @@ public void Behavior_WithBoundsChangedDelegate_ShouldSelectNodesInsideArea() { // Arrange var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramDragBehavior = typeof(SelectionBoxBehavior); + diagram.Options.Behaviors.DiagramDragBehavior = diagram.GetBehavior(); diagram.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); var selectionBoxBehavior = diagram.GetBehavior()!; @@ -104,7 +104,7 @@ public void Behavior_WithoutBoundsChangedDelegate_ShouldNotSelectNodesInsideArea { // Arrange var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramDragBehavior = typeof(SelectionBoxBehavior); + diagram.Options.Behaviors.DiagramDragBehavior = diagram.GetBehavior(); diagram.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); var node = new NodeModel() diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviorTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviorTests.cs index 89cf5ef2d..aed9c3051 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviorTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviorTests.cs @@ -12,7 +12,7 @@ public void Behavior_WhenBehaviorEnabled_ShouldZoom() { // Arrange var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramWheelBehavior = typeof(ZoomBehavior); + diagram.Options.Behaviors.DiagramWheelBehavior = diagram.GetBehavior(); diagram.SetContainer(new Rectangle(0, 0, 100, 100)); // Act diff --git a/tests/Blazor.Diagrams.Core.Tests/Options/DiagramBehaviorOptionsTests.cs b/tests/Blazor.Diagrams.Core.Tests/Options/DiagramBehaviorOptionsTests.cs index 188e9e267..41dc5e0de 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Options/DiagramBehaviorOptionsTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Options/DiagramBehaviorOptionsTests.cs @@ -19,7 +19,7 @@ public void DiagramBehaviorOptions_DragBehavior_IsBehaviorEnabled() diagram.Options.Behaviors.DiagramDragBehavior = null; Assert.False(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true))); - diagram.Options.Behaviors.DiagramDragBehavior = typeof(PanBehavior); + diagram.Options.Behaviors.DiagramDragBehavior = diagram.GetBehavior(); Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true))); } @@ -27,14 +27,14 @@ public void DiagramBehaviorOptions_DragBehavior_IsBehaviorEnabled() public void DiagramBehaviorOptions_AltDragBehavior_IsBehaviorEnabled() { var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramDragBehavior = typeof(PanBehavior); + diagram.Options.Behaviors.DiagramDragBehavior = diagram.GetBehavior(); diagram.Options.Behaviors.DiagramAltDragBehavior = null; Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, false, true, 0, 0, 0, 0, 0, 0, string.Empty, true))); diagram.Options.Behaviors.DiagramDragBehavior = null; Assert.False(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, false, true, 0, 0, 0, 0, 0, 0, string.Empty, true))); - diagram.Options.Behaviors.DiagramAltDragBehavior = typeof(PanBehavior); + diagram.Options.Behaviors.DiagramAltDragBehavior = diagram.GetBehavior(); Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, false, true, 0, 0, 0, 0, 0, 0, string.Empty, true))); } @@ -42,14 +42,14 @@ public void DiagramBehaviorOptions_AltDragBehavior_IsBehaviorEnabled() public void DiagramBehaviorOptions_CtrlDragBehavior_IsBehaviorEnabled() { var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramDragBehavior = typeof(PanBehavior); + diagram.Options.Behaviors.DiagramDragBehavior = diagram.GetBehavior(); diagram.Options.Behaviors.DiagramCtrlDragBehavior = null; Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, true, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true))); diagram.Options.Behaviors.DiagramDragBehavior = null; Assert.False(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, true, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true))); - diagram.Options.Behaviors.DiagramCtrlDragBehavior = typeof(PanBehavior); + diagram.Options.Behaviors.DiagramCtrlDragBehavior = diagram.GetBehavior(); Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, true, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true))); } @@ -57,14 +57,14 @@ public void DiagramBehaviorOptions_CtrlDragBehavior_IsBehaviorEnabled() public void DiagramBehaviorOptions_ShiftDragBehavior_IsBehaviorEnabled() { var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramDragBehavior = typeof(PanBehavior); + diagram.Options.Behaviors.DiagramDragBehavior = diagram.GetBehavior(); diagram.Options.Behaviors.DiagramShiftDragBehavior = null; Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, true, false, 0, 0, 0, 0, 0, 0, string.Empty, true))); diagram.Options.Behaviors.DiagramDragBehavior = null; Assert.False(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, true, false, 0, 0, 0, 0, 0, 0, string.Empty, true))); - diagram.Options.Behaviors.DiagramShiftDragBehavior = typeof(PanBehavior); + diagram.Options.Behaviors.DiagramShiftDragBehavior = diagram.GetBehavior(); Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, true, false, 0, 0, 0, 0, 0, 0, string.Empty, true))); } @@ -75,7 +75,7 @@ public void DiagramBehaviorOptions_DefaultScrollBehavior_IsBehaviorEnabled() diagram.Options.Behaviors.DiagramWheelBehavior = null; Assert.False(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, false, false, 0, 0, 0, 0))); - diagram.Options.Behaviors.DiagramWheelBehavior = typeof(ZoomBehavior); + diagram.Options.Behaviors.DiagramWheelBehavior = diagram.GetBehavior(); Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, false, false, 0, 0, 0, 0))); } @@ -83,14 +83,14 @@ public void DiagramBehaviorOptions_DefaultScrollBehavior_IsBehaviorEnabled() public void DiagramBehaviorOptions_AltScrollBehavior_IsBehaviorEnabled() { var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramWheelBehavior = typeof(ZoomBehavior); + diagram.Options.Behaviors.DiagramWheelBehavior = diagram.GetBehavior(); diagram.Options.Behaviors.DiagramAltWheelBehavior = null; Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, false, true, 0, 0, 0, 0))); diagram.Options.Behaviors.DiagramWheelBehavior = null; Assert.False(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, false, true, 0, 0, 0, 0))); - diagram.Options.Behaviors.DiagramAltWheelBehavior = typeof(ZoomBehavior); + diagram.Options.Behaviors.DiagramAltWheelBehavior = diagram.GetBehavior(); Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, false, true, 0, 0, 0, 0))); } @@ -98,14 +98,14 @@ public void DiagramBehaviorOptions_AltScrollBehavior_IsBehaviorEnabled() public void DiagramBehaviorOptions_CtrlScrollBehavior_IsBehaviorEnabled() { var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramWheelBehavior = typeof(ZoomBehavior); + diagram.Options.Behaviors.DiagramWheelBehavior = diagram.GetBehavior(); diagram.Options.Behaviors.DiagramCtrlWheelBehavior = null; Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, true, false, false, 0, 0, 0, 0))); diagram.Options.Behaviors.DiagramWheelBehavior = null; Assert.False(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, true, false, false, 0, 0, 0, 0))); - diagram.Options.Behaviors.DiagramCtrlWheelBehavior = typeof(ZoomBehavior); + diagram.Options.Behaviors.DiagramCtrlWheelBehavior = diagram.GetBehavior(); Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, true, false, false, 0, 0, 0, 0))); } @@ -113,14 +113,14 @@ public void DiagramBehaviorOptions_CtrlScrollBehavior_IsBehaviorEnabled() public void DiagramBehaviorOptions_ShiftScrollBehavior_IsBehaviorEnabled() { var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramWheelBehavior = typeof(ZoomBehavior); + diagram.Options.Behaviors.DiagramWheelBehavior = diagram.GetBehavior(); diagram.Options.Behaviors.DiagramShiftWheelBehavior = null; Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, true, false, 0, 0, 0, 0))); diagram.Options.Behaviors.DiagramWheelBehavior = null; Assert.False(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, true, false, 0, 0, 0, 0))); - diagram.Options.Behaviors.DiagramShiftWheelBehavior = typeof(ZoomBehavior); + diagram.Options.Behaviors.DiagramShiftWheelBehavior = diagram.GetBehavior(); Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, true, false, 0, 0, 0, 0))); } } diff --git a/tests/Blazor.Diagrams.Tests/Components/Widgets/SelectionBoxWidgetTests.cs b/tests/Blazor.Diagrams.Tests/Components/Widgets/SelectionBoxWidgetTests.cs index d43368f0e..f2310dc58 100644 --- a/tests/Blazor.Diagrams.Tests/Components/Widgets/SelectionBoxWidgetTests.cs +++ b/tests/Blazor.Diagrams.Tests/Components/Widgets/SelectionBoxWidgetTests.cs @@ -16,7 +16,7 @@ public void SelectionBoxWidget_SelectionBoundsChanged_RendersSelectionBoxWidgetI // Arrange using var ctx = new TestContext(); var diagram = new BlazorDiagram(); - diagram.Options.Behaviors.DiagramDragBehavior = typeof(SelectionBoxBehavior); + diagram.Options.Behaviors.DiagramDragBehavior = diagram.GetBehavior(); diagram.SetPan(-75, -100); diagram.SetContainer(new Rectangle(new Point(0, 0), new Size(500, 500))); From f66883d9cebab5b58a2cda74f577374dd806c734 Mon Sep 17 00:00:00 2001 From: Matt Swain Date: Wed, 24 May 2023 15:49:04 +1000 Subject: [PATCH 09/17] refactor --- .../Behaviors/Base/DragBehavior.cs | 14 ++-- .../Behaviors/Base/WheelBehavior.cs | 14 ++-- src/Blazor.Diagrams.Core/Diagram.cs | 73 +++++++++++-------- .../Options/DiagramOptions.cs | 1 - src/Blazor.Diagrams/BlazorDiagram.cs | 3 - .../Options/BlazorDiagramBehaviorOptions.cs | 13 ---- .../Options/BlazorDiagramOptions.cs | 1 - .../Behaviors/PanBehaviorTests.cs | 4 +- .../Behaviors/ScrollBehaviorTests.cs | 4 +- .../Behaviors/SelectionBoxBehaviorTests.cs | 8 +- .../Behaviors/ZoomBehaviorTests.cs | 4 +- .../Options/DiagramBehaviorOptionsTests.cs | 56 +++++++------- .../Widgets/SelectionBoxWidgetTests.cs | 2 +- 13 files changed, 95 insertions(+), 102 deletions(-) delete mode 100644 src/Blazor.Diagrams/Options/BlazorDiagramBehaviorOptions.cs diff --git a/src/Blazor.Diagrams.Core/Behaviors/Base/DragBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/Base/DragBehavior.cs index 0c11b180d..3985dd241 100644 --- a/src/Blazor.Diagrams.Core/Behaviors/Base/DragBehavior.cs +++ b/src/Blazor.Diagrams.Core/Behaviors/Base/DragBehavior.cs @@ -22,21 +22,21 @@ public DragBehavior(Diagram diagram) public virtual bool IsBehaviorEnabled(PointerEventArgs e) { if (e.AltKey && !e.CtrlKey && !e.ShiftKey - && Diagram.Options.Behaviors.DiagramAltDragBehavior is not null) + && Diagram.BehaviorOptions.DiagramAltDragBehavior is not null) { - return this == Diagram.Options.Behaviors.DiagramAltDragBehavior; + return this == Diagram.BehaviorOptions.DiagramAltDragBehavior; } else if (!e.AltKey && e.CtrlKey && !e.ShiftKey - && Diagram.Options.Behaviors.DiagramCtrlDragBehavior is not null) + && Diagram.BehaviorOptions.DiagramCtrlDragBehavior is not null) { - return this == Diagram.Options.Behaviors.DiagramCtrlDragBehavior; + return this == Diagram.BehaviorOptions.DiagramCtrlDragBehavior; } else if (!e.AltKey && !e.CtrlKey && e.ShiftKey - && Diagram.Options.Behaviors.DiagramShiftDragBehavior is not null) + && Diagram.BehaviorOptions.DiagramShiftDragBehavior is not null) { - return this == Diagram.Options.Behaviors.DiagramShiftDragBehavior; + return this == Diagram.BehaviorOptions.DiagramShiftDragBehavior; } - return this == Diagram.Options.Behaviors.DiagramDragBehavior; + return this == Diagram.BehaviorOptions.DiagramDragBehavior; } public override void Dispose() diff --git a/src/Blazor.Diagrams.Core/Behaviors/Base/WheelBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/Base/WheelBehavior.cs index cbaba03b2..01792efc5 100644 --- a/src/Blazor.Diagrams.Core/Behaviors/Base/WheelBehavior.cs +++ b/src/Blazor.Diagrams.Core/Behaviors/Base/WheelBehavior.cs @@ -16,22 +16,22 @@ protected WheelBehavior(Diagram diagram) public virtual bool IsBehaviorEnabled(WheelEventArgs e) { if (e.AltKey && !e.CtrlKey && !e.ShiftKey - && Diagram.Options.Behaviors.DiagramAltWheelBehavior is not null) + && Diagram.BehaviorOptions.DiagramAltWheelBehavior is not null) { - return this == Diagram.Options.Behaviors.DiagramAltWheelBehavior; + return this == Diagram.BehaviorOptions.DiagramAltWheelBehavior; } else if (!e.AltKey && e.CtrlKey && !e.ShiftKey - && Diagram.Options.Behaviors.DiagramCtrlWheelBehavior is not null) + && Diagram.BehaviorOptions.DiagramCtrlWheelBehavior is not null) { - return this == Diagram.Options.Behaviors.DiagramCtrlWheelBehavior; + return this == Diagram.BehaviorOptions.DiagramCtrlWheelBehavior; } else if (!e.AltKey && !e.CtrlKey && e.ShiftKey - && Diagram.Options.Behaviors.DiagramShiftWheelBehavior is not null) + && Diagram.BehaviorOptions.DiagramShiftWheelBehavior is not null) { - return this == Diagram.Options.Behaviors.DiagramShiftWheelBehavior; + return this == Diagram.BehaviorOptions.DiagramShiftWheelBehavior; } - return this == Diagram.Options.Behaviors.DiagramWheelBehavior; + return this == Diagram.BehaviorOptions.DiagramWheelBehavior; } public override void Dispose() diff --git a/src/Blazor.Diagrams.Core/Diagram.cs b/src/Blazor.Diagrams.Core/Diagram.cs index 22ea58cbc..94a0074c5 100644 --- a/src/Blazor.Diagrams.Core/Diagram.cs +++ b/src/Blazor.Diagrams.Core/Diagram.cs @@ -44,10 +44,11 @@ protected Diagram() _behaviors = new Dictionary(); _orderedSelectables = new List(); - Nodes = new NodeLayer(this); - Links = new LinkLayer(this); - Groups = new GroupLayer(this); - Controls = new ControlsLayer(); + Nodes = new NodeLayer(this); + Links = new LinkLayer(this); + Groups = new GroupLayer(this); + Controls = new ControlsLayer(); + BehaviorOptions = new DiagramBehaviorOptions(); Nodes.Added += OnSelectableAdded; Links.Added += OnSelectableAdded; @@ -57,30 +58,25 @@ protected Diagram() Links.Removed += OnSelectableRemoved; Groups.Removed += OnSelectableRemoved; - RegisterBehavior(new SelectionBehavior(this)); - RegisterBehavior(new DragMovablesBehavior(this)); - RegisterBehavior(new DragNewLinkBehavior(this)); - RegisterBehavior(new PanBehavior(this)); - RegisterBehavior(new ZoomBehavior(this)); - RegisterBehavior(new EventsBehavior(this)); - RegisterBehavior(new KeyboardShortcutsBehavior(this)); - RegisterBehavior(new ControlsBehavior(this)); - RegisterBehavior(new VirtualizationBehavior(this)); - RegisterBehavior(new ScrollBehavior(this)); - RegisterBehavior(new SelectionBoxBehavior(this)); + RegisterDefaultBehaviors(); + + BehaviorOptions.DiagramDragBehavior ??= GetBehavior(); + BehaviorOptions.DiagramShiftDragBehavior ??= GetBehavior(); + BehaviorOptions.DiagramWheelBehavior ??= GetBehavior(); } - public abstract DiagramOptions Options { get; } - public NodeLayer Nodes { get; } - public LinkLayer Links { get; } - public GroupLayer Groups { get; } - public ControlsLayer Controls { get; } - public Rectangle? Container { get; private set; } - public Point Pan { get; private set; } = Point.Zero; - public double Zoom { get; private set; } = 1; - public bool SuspendRefresh { get; set; } - public bool SuspendSorting { get; set; } - public IReadOnlyList OrderedSelectables => _orderedSelectables; + public abstract DiagramOptions Options { get; } + public DiagramBehaviorOptions BehaviorOptions { get; } + public NodeLayer Nodes { get; } + public LinkLayer Links { get; } + public GroupLayer Groups { get; } + public ControlsLayer Controls { get; } + public Rectangle? Container { get; private set; } + public Point Pan { get; private set; } = Point.Zero; + public double Zoom { get; private set; } = 1; + public bool SuspendRefresh { get; set; } + public bool SuspendSorting { get; set; } + public IReadOnlyList OrderedSelectables => _orderedSelectables; public void Refresh() { @@ -173,11 +169,26 @@ public void UnselectAll() #region Behaviors - public void RegisterBehavior(Behavior behavior) - { - var type = behavior.GetType(); - if (_behaviors.ContainsKey(type)) - throw new Exception($"Behavior '{type.Name}' already registered"); + void RegisterDefaultBehaviors() + { + RegisterBehavior(new SelectionBehavior(this)); + RegisterBehavior(new DragMovablesBehavior(this)); + RegisterBehavior(new DragNewLinkBehavior(this)); + RegisterBehavior(new PanBehavior(this)); + RegisterBehavior(new ZoomBehavior(this)); + RegisterBehavior(new EventsBehavior(this)); + RegisterBehavior(new KeyboardShortcutsBehavior(this)); + RegisterBehavior(new ControlsBehavior(this)); + RegisterBehavior(new VirtualizationBehavior(this)); + RegisterBehavior(new ScrollBehavior(this)); + RegisterBehavior(new SelectionBoxBehavior(this)); + } + + public void RegisterBehavior(Behavior behavior) + { + var type = behavior.GetType(); + if (_behaviors.ContainsKey(type)) + throw new Exception($"Behavior '{type.Name}' already registered"); _behaviors.Add(type, behavior); } diff --git a/src/Blazor.Diagrams.Core/Options/DiagramOptions.cs b/src/Blazor.Diagrams.Core/Options/DiagramOptions.cs index 5dc985adb..9fcb6ed0e 100644 --- a/src/Blazor.Diagrams.Core/Options/DiagramOptions.cs +++ b/src/Blazor.Diagrams.Core/Options/DiagramOptions.cs @@ -14,5 +14,4 @@ public class DiagramOptions public virtual DiagramGroupOptions Groups { get; } = new(); public virtual DiagramConstraintsOptions Constraints { get; } = new(); public virtual DiagramVirtualizationOptions Virtualization { get; } = new(); - public virtual DiagramBehaviorOptions Behaviors { get; } = new(); } \ No newline at end of file diff --git a/src/Blazor.Diagrams/BlazorDiagram.cs b/src/Blazor.Diagrams/BlazorDiagram.cs index 65e6ef6d3..0b087c89b 100644 --- a/src/Blazor.Diagrams/BlazorDiagram.cs +++ b/src/Blazor.Diagrams/BlazorDiagram.cs @@ -24,9 +24,6 @@ public BlazorDiagram(BlazorDiagramOptions? options = null) }; Options = options ?? new BlazorDiagramOptions(); - Options.Behaviors.DiagramDragBehavior ??= GetBehavior(); - Options.Behaviors.DiagramShiftDragBehavior ??= GetBehavior(); - Options.Behaviors.DiagramWheelBehavior ??= GetBehavior(); } public override BlazorDiagramOptions Options { get; } diff --git a/src/Blazor.Diagrams/Options/BlazorDiagramBehaviorOptions.cs b/src/Blazor.Diagrams/Options/BlazorDiagramBehaviorOptions.cs deleted file mode 100644 index 82643a268..000000000 --- a/src/Blazor.Diagrams/Options/BlazorDiagramBehaviorOptions.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Blazor.Diagrams.Core.Options; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Blazor.Diagrams.Options -{ - public class BlazorDiagramBehaviorOptions : DiagramBehaviorOptions - { - } -} diff --git a/src/Blazor.Diagrams/Options/BlazorDiagramOptions.cs b/src/Blazor.Diagrams/Options/BlazorDiagramOptions.cs index 11093f5b0..b7ea0e63e 100644 --- a/src/Blazor.Diagrams/Options/BlazorDiagramOptions.cs +++ b/src/Blazor.Diagrams/Options/BlazorDiagramOptions.cs @@ -12,5 +12,4 @@ public class BlazorDiagramOptions : DiagramOptions public override BlazorDiagramGroupOptions Groups { get; } = new(); public override BlazorDiagramConstraintsOptions Constraints { get; } = new(); public override BlazorDiagramVirtualizationOptions Virtualization { get; } = new(); - public override BlazorDiagramBehaviorOptions Behaviors { get; } = new(); } \ No newline at end of file diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviorTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviorTests.cs index da2fa3368..3feee5090 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviorTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/PanBehaviorTests.cs @@ -12,7 +12,7 @@ public void Behavior_WhenBehaviorEnabled_ShouldPan() { // Arrange var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramDragBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramDragBehavior = diagram.GetBehavior(); diagram.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); Assert.Equal(0, diagram.Pan.X); @@ -34,7 +34,7 @@ public void Behavior_WhenBehaviorDisabled_ShouldNotPan() { // Arrange var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramDragBehavior = null; + diagram.BehaviorOptions.DiagramDragBehavior = null; diagram.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); Assert.Equal(0, diagram.Pan.X); diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviorTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviorTests.cs index 556a7a26c..acd78bbdc 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviorTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ScrollBehaviorTests.cs @@ -12,7 +12,7 @@ public void Behavior_WhenBehaviorEnabled_ShouldScroll() { // Arrange var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramWheelBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramWheelBehavior = diagram.GetBehavior(); diagram.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); diagram.Options.Zoom.ScaleFactor = 1.05; @@ -29,7 +29,7 @@ public void Behavior_WhenBehaviorDisabled_ShouldNotScroll() { // Arrange var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramWheelBehavior = null; + diagram.BehaviorOptions.DiagramWheelBehavior = null; diagram.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); // Act diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs index 2f9f90e32..ba0d94d6d 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs @@ -13,7 +13,7 @@ public void Behavior_WhenBehaviorEnabled_ShouldUpdateSelectionBounds() { // Arrange var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramDragBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramDragBehavior = diagram.GetBehavior(); diagram.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); var selectionBoxBehavior = diagram.GetBehavior()!; @@ -44,7 +44,7 @@ public void Behavior_WhenBehaviorDisabled_ShouldNotUpdateSelectionBounds() { // Arrange var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramDragBehavior = null; + diagram.BehaviorOptions.DiagramDragBehavior = null; diagram.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); var selectionBoxBehavior = diagram.GetBehavior()!; @@ -72,7 +72,7 @@ public void Behavior_WithBoundsChangedDelegate_ShouldSelectNodesInsideArea() { // Arrange var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramDragBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramDragBehavior = diagram.GetBehavior(); diagram.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); var selectionBoxBehavior = diagram.GetBehavior()!; @@ -104,7 +104,7 @@ public void Behavior_WithoutBoundsChangedDelegate_ShouldNotSelectNodesInsideArea { // Arrange var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramDragBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramDragBehavior = diagram.GetBehavior(); diagram.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); var node = new NodeModel() diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviorTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviorTests.cs index aed9c3051..526c9b6c9 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviorTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/ZoomBehaviorTests.cs @@ -12,7 +12,7 @@ public void Behavior_WhenBehaviorEnabled_ShouldZoom() { // Arrange var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramWheelBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramWheelBehavior = diagram.GetBehavior(); diagram.SetContainer(new Rectangle(0, 0, 100, 100)); // Act @@ -27,7 +27,7 @@ public void Behavior_WhenBehaviorDisabled_ShouldNotZoom() { // Arrange var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramWheelBehavior = null; + diagram.BehaviorOptions.DiagramWheelBehavior = null; diagram.SetContainer(new Rectangle(0, 0, 100, 100)); // Act diff --git a/tests/Blazor.Diagrams.Core.Tests/Options/DiagramBehaviorOptionsTests.cs b/tests/Blazor.Diagrams.Core.Tests/Options/DiagramBehaviorOptionsTests.cs index 41dc5e0de..62e73a38f 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Options/DiagramBehaviorOptionsTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Options/DiagramBehaviorOptionsTests.cs @@ -16,10 +16,10 @@ public class DiagramBehaviorOptionsTests public void DiagramBehaviorOptions_DragBehavior_IsBehaviorEnabled() { var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramDragBehavior = null; + diagram.BehaviorOptions.DiagramDragBehavior = null; Assert.False(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true))); - diagram.Options.Behaviors.DiagramDragBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramDragBehavior = diagram.GetBehavior(); Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true))); } @@ -27,14 +27,14 @@ public void DiagramBehaviorOptions_DragBehavior_IsBehaviorEnabled() public void DiagramBehaviorOptions_AltDragBehavior_IsBehaviorEnabled() { var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramDragBehavior = diagram.GetBehavior(); - diagram.Options.Behaviors.DiagramAltDragBehavior = null; + diagram.BehaviorOptions.DiagramDragBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramAltDragBehavior = null; Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, false, true, 0, 0, 0, 0, 0, 0, string.Empty, true))); - diagram.Options.Behaviors.DiagramDragBehavior = null; + diagram.BehaviorOptions.DiagramDragBehavior = null; Assert.False(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, false, true, 0, 0, 0, 0, 0, 0, string.Empty, true))); - diagram.Options.Behaviors.DiagramAltDragBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramAltDragBehavior = diagram.GetBehavior(); Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, false, true, 0, 0, 0, 0, 0, 0, string.Empty, true))); } @@ -42,14 +42,14 @@ public void DiagramBehaviorOptions_AltDragBehavior_IsBehaviorEnabled() public void DiagramBehaviorOptions_CtrlDragBehavior_IsBehaviorEnabled() { var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramDragBehavior = diagram.GetBehavior(); - diagram.Options.Behaviors.DiagramCtrlDragBehavior = null; + diagram.BehaviorOptions.DiagramDragBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramCtrlDragBehavior = null; Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, true, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true))); - diagram.Options.Behaviors.DiagramDragBehavior = null; + diagram.BehaviorOptions.DiagramDragBehavior = null; Assert.False(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, true, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true))); - diagram.Options.Behaviors.DiagramCtrlDragBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramCtrlDragBehavior = diagram.GetBehavior(); Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, true, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true))); } @@ -57,14 +57,14 @@ public void DiagramBehaviorOptions_CtrlDragBehavior_IsBehaviorEnabled() public void DiagramBehaviorOptions_ShiftDragBehavior_IsBehaviorEnabled() { var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramDragBehavior = diagram.GetBehavior(); - diagram.Options.Behaviors.DiagramShiftDragBehavior = null; + diagram.BehaviorOptions.DiagramDragBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramShiftDragBehavior = null; Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, true, false, 0, 0, 0, 0, 0, 0, string.Empty, true))); - diagram.Options.Behaviors.DiagramDragBehavior = null; + diagram.BehaviorOptions.DiagramDragBehavior = null; Assert.False(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, true, false, 0, 0, 0, 0, 0, 0, string.Empty, true))); - diagram.Options.Behaviors.DiagramShiftDragBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramShiftDragBehavior = diagram.GetBehavior(); Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new PointerEventArgs(0, 0, 0, 0, false, true, false, 0, 0, 0, 0, 0, 0, string.Empty, true))); } @@ -72,10 +72,10 @@ public void DiagramBehaviorOptions_ShiftDragBehavior_IsBehaviorEnabled() public void DiagramBehaviorOptions_DefaultScrollBehavior_IsBehaviorEnabled() { var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramWheelBehavior = null; + diagram.BehaviorOptions.DiagramWheelBehavior = null; Assert.False(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, false, false, 0, 0, 0, 0))); - diagram.Options.Behaviors.DiagramWheelBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramWheelBehavior = diagram.GetBehavior(); Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, false, false, 0, 0, 0, 0))); } @@ -83,14 +83,14 @@ public void DiagramBehaviorOptions_DefaultScrollBehavior_IsBehaviorEnabled() public void DiagramBehaviorOptions_AltScrollBehavior_IsBehaviorEnabled() { var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramWheelBehavior = diagram.GetBehavior(); - diagram.Options.Behaviors.DiagramAltWheelBehavior = null; + diagram.BehaviorOptions.DiagramWheelBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramAltWheelBehavior = null; Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, false, true, 0, 0, 0, 0))); - diagram.Options.Behaviors.DiagramWheelBehavior = null; + diagram.BehaviorOptions.DiagramWheelBehavior = null; Assert.False(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, false, true, 0, 0, 0, 0))); - diagram.Options.Behaviors.DiagramAltWheelBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramAltWheelBehavior = diagram.GetBehavior(); Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, false, true, 0, 0, 0, 0))); } @@ -98,14 +98,14 @@ public void DiagramBehaviorOptions_AltScrollBehavior_IsBehaviorEnabled() public void DiagramBehaviorOptions_CtrlScrollBehavior_IsBehaviorEnabled() { var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramWheelBehavior = diagram.GetBehavior(); - diagram.Options.Behaviors.DiagramCtrlWheelBehavior = null; + diagram.BehaviorOptions.DiagramWheelBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramCtrlWheelBehavior = null; Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, true, false, false, 0, 0, 0, 0))); - diagram.Options.Behaviors.DiagramWheelBehavior = null; + diagram.BehaviorOptions.DiagramWheelBehavior = null; Assert.False(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, true, false, false, 0, 0, 0, 0))); - diagram.Options.Behaviors.DiagramCtrlWheelBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramCtrlWheelBehavior = diagram.GetBehavior(); Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, true, false, false, 0, 0, 0, 0))); } @@ -113,14 +113,14 @@ public void DiagramBehaviorOptions_CtrlScrollBehavior_IsBehaviorEnabled() public void DiagramBehaviorOptions_ShiftScrollBehavior_IsBehaviorEnabled() { var diagram = new TestDiagram(); - diagram.Options.Behaviors.DiagramWheelBehavior = diagram.GetBehavior(); - diagram.Options.Behaviors.DiagramShiftWheelBehavior = null; + diagram.BehaviorOptions.DiagramWheelBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramShiftWheelBehavior = null; Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, true, false, 0, 0, 0, 0))); - diagram.Options.Behaviors.DiagramWheelBehavior = null; + diagram.BehaviorOptions.DiagramWheelBehavior = null; Assert.False(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, true, false, 0, 0, 0, 0))); - diagram.Options.Behaviors.DiagramShiftWheelBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramShiftWheelBehavior = diagram.GetBehavior(); Assert.True(diagram.GetBehavior()!.IsBehaviorEnabled(new WheelEventArgs(0, 0, 0, 0, false, true, false, 0, 0, 0, 0))); } } diff --git a/tests/Blazor.Diagrams.Tests/Components/Widgets/SelectionBoxWidgetTests.cs b/tests/Blazor.Diagrams.Tests/Components/Widgets/SelectionBoxWidgetTests.cs index f2310dc58..11d913539 100644 --- a/tests/Blazor.Diagrams.Tests/Components/Widgets/SelectionBoxWidgetTests.cs +++ b/tests/Blazor.Diagrams.Tests/Components/Widgets/SelectionBoxWidgetTests.cs @@ -16,7 +16,7 @@ public void SelectionBoxWidget_SelectionBoundsChanged_RendersSelectionBoxWidgetI // Arrange using var ctx = new TestContext(); var diagram = new BlazorDiagram(); - diagram.Options.Behaviors.DiagramDragBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramDragBehavior = diagram.GetBehavior(); diagram.SetPan(-75, -100); diagram.SetContainer(new Rectangle(new Point(0, 0), new Size(500, 500))); From 91f47cb85d91de096c8c267c1f52c48ba30ee7c7 Mon Sep 17 00:00:00 2001 From: Shams Azam Date: Thu, 18 Jul 2024 14:55:48 +0530 Subject: [PATCH 10/17] fixed build issues --- .../Behaviors/Base/Behavior.cs | 5 +-- src/Blazor.Diagrams.Core/Diagram.cs | 35 +++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/Blazor.Diagrams.Core/Behaviors/Base/Behavior.cs b/src/Blazor.Diagrams.Core/Behaviors/Base/Behavior.cs index 617447e7c..260164fd9 100644 --- a/src/Blazor.Diagrams.Core/Behaviors/Base/Behavior.cs +++ b/src/Blazor.Diagrams.Core/Behaviors/Base/Behavior.cs @@ -9,7 +9,8 @@ public Behavior(Diagram diagram) Diagram = diagram; } - protected Diagram Diagram { get; } + protected Diagram Diagram { get; } - public abstract void Dispose(); + public abstract void Dispose(); + } } diff --git a/src/Blazor.Diagrams.Core/Diagram.cs b/src/Blazor.Diagrams.Core/Diagram.cs index 94a0074c5..e63e832e7 100644 --- a/src/Blazor.Diagrams.Core/Diagram.cs +++ b/src/Blazor.Diagrams.Core/Diagram.cs @@ -58,25 +58,25 @@ protected Diagram() Links.Removed += OnSelectableRemoved; Groups.Removed += OnSelectableRemoved; - RegisterDefaultBehaviors(); + RegisterDefaultBehaviors(); - BehaviorOptions.DiagramDragBehavior ??= GetBehavior(); - BehaviorOptions.DiagramShiftDragBehavior ??= GetBehavior(); - BehaviorOptions.DiagramWheelBehavior ??= GetBehavior(); - } + BehaviorOptions.DiagramDragBehavior ??= GetBehavior(); + BehaviorOptions.DiagramShiftDragBehavior ??= GetBehavior(); + BehaviorOptions.DiagramWheelBehavior ??= GetBehavior(); + } - public abstract DiagramOptions Options { get; } - public DiagramBehaviorOptions BehaviorOptions { get; } - public NodeLayer Nodes { get; } - public LinkLayer Links { get; } - public GroupLayer Groups { get; } - public ControlsLayer Controls { get; } - public Rectangle? Container { get; private set; } - public Point Pan { get; private set; } = Point.Zero; - public double Zoom { get; private set; } = 1; - public bool SuspendRefresh { get; set; } - public bool SuspendSorting { get; set; } - public IReadOnlyList OrderedSelectables => _orderedSelectables; + public abstract DiagramOptions Options { get; } + public DiagramBehaviorOptions BehaviorOptions { get; } + public NodeLayer Nodes { get; } + public LinkLayer Links { get; } + public GroupLayer Groups { get; } + public ControlsLayer Controls { get; } + public Rectangle? Container { get; private set; } + public Point Pan { get; private set; } = Point.Zero; + public double Zoom { get; private set; } = 1; + public bool SuspendRefresh { get; set; } + public bool SuspendSorting { get; set; } + public IReadOnlyList OrderedSelectables => _orderedSelectables; public void Refresh() { @@ -417,5 +417,4 @@ private void OnModelOrderChanged(Model model) public void TriggerPointerDoubleClick(Model? model, PointerEventArgs e) => PointerDoubleClick?.Invoke(model, e); #endregion - } } \ No newline at end of file From 302efd964b6f8b00314ddd022d1c3c851cb2f26c Mon Sep 17 00:00:00 2001 From: Shams Azam Date: Thu, 18 Jul 2024 15:38:36 +0530 Subject: [PATCH 11/17] fixed build error from DragNewLinkBehavior --- src/Blazor.Diagrams.Core/Behaviors/DragNewLinkBehavior.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Blazor.Diagrams.Core/Behaviors/DragNewLinkBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/DragNewLinkBehavior.cs index 3796f2c95..37f58afe9 100644 --- a/src/Blazor.Diagrams.Core/Behaviors/DragNewLinkBehavior.cs +++ b/src/Blazor.Diagrams.Core/Behaviors/DragNewLinkBehavior.cs @@ -3,6 +3,7 @@ using Blazor.Diagrams.Core.Events; using System.Linq; using Blazor.Diagrams.Core.Anchors; +using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Core.Behaviors.Base; namespace Blazor.Diagrams.Core.Behaviors; From 28d2d6b64df9b0463659f685436a55a9a3ffdf46 Mon Sep 17 00:00:00 2001 From: Shams Azam Date: Thu, 18 Jul 2024 15:47:49 +0530 Subject: [PATCH 12/17] fixed RemoveControlTest build error --- .../Controls/RemoveControlTests.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/Blazor.Diagrams.Core.Tests/Controls/RemoveControlTests.cs b/tests/Blazor.Diagrams.Core.Tests/Controls/RemoveControlTests.cs index 1b2201ef5..54a531908 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Controls/RemoveControlTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Controls/RemoveControlTests.cs @@ -40,7 +40,7 @@ public async Task OnPointerDown_ShouldDeleteNodeTrue_RemovesNode() // Arrange RemoveControl removeControl = new(0, 0); Diagram diagram = new TestDiagram( - new Options.DiagramOptions + new Core.Options.DiagramOptions { Constraints = { @@ -63,7 +63,7 @@ public async Task OnPointerDown_ShouldDeleteNodeFalse_KeepsNode() // Arrange RemoveControl removeControl = new(0, 0); Diagram diagram = new TestDiagram( - new Options.DiagramOptions + new Core.Options.DiagramOptions { Constraints = { @@ -113,7 +113,7 @@ public async Task OnPointerDown_ShouldDeleteLinkTrue_RemovesLink() // Arrange RemoveControl removeControl = new(0, 0); Diagram diagram = new TestDiagram( - new Options.DiagramOptions + new Core.Options.DiagramOptions { Constraints = { @@ -147,7 +147,7 @@ public async Task OnPointerDown_ShouldDeleteLinkFalse_KeepsLink() // Arrange RemoveControl removeControl = new(0, 0); Diagram diagram = new TestDiagram( - new Options.DiagramOptions + new Core.Options.DiagramOptions { Constraints = { @@ -207,7 +207,7 @@ public async Task OnPointerDown_ShouldDeleteGroupTrue_RemovesGroup() // Arrange RemoveControl removeControl = new(0, 0); Diagram diagram = new TestDiagram( - new Options.DiagramOptions + new Core.Options.DiagramOptions { Constraints = { @@ -240,7 +240,7 @@ public async Task OnPointerDown_ShouldDeleteGroupFalse_KeepsGroup() // Arrange RemoveControl removeControl = new(0, 0); Diagram diagram = new TestDiagram( - new Options.DiagramOptions + new Core.Options.DiagramOptions { Constraints = { From 9e3c615ea123156d8112539ff447c769c446f6eb Mon Sep 17 00:00:00 2001 From: Shams Azam Date: Thu, 4 Jul 2024 08:07:31 +0530 Subject: [PATCH 13/17] WI00761833 - Updates for Blazor Diagrams mouse configuration --- .../Pages/Documentation/Diagram/Behaviors.razor | 14 ++++++++++++++ .../Components/DiagramCanvas.razor.cs | 3 ++- .../Extensions/JSRuntimeExtensions.cs | 5 +++++ src/Blazor.Diagrams/wwwroot/script.js | 3 +++ src/Blazor.Diagrams/wwwroot/script.min.js | 2 +- 5 files changed, 25 insertions(+), 2 deletions(-) diff --git a/site/Site/Pages/Documentation/Diagram/Behaviors.razor b/site/Site/Pages/Documentation/Diagram/Behaviors.razor index 540daba7e..4f3785adc 100644 --- a/site/Site/Pages/Documentation/Diagram/Behaviors.razor +++ b/site/Site/Pages/Documentation/Diagram/Behaviors.razor @@ -114,6 +114,20 @@ Diagram.UnregisterBehavior<SelectionBehavior>(); Diagram.RegisterBehavior(new MySelectionBehavior(Diagram)); +

Using Different Behaviors

+ +You can use the following ways to add different behaviors to the diagram. + +

Scroll Behavior

+ +

To scroll the diagram using the mouse wheel you can register the Scroll Behavior.

+ +

+Diagram.UnregisterBehavior<WheelBehavior>();
+Diagram.RegisterBehavior(new ScrollBehavior(Diagram));
+
+ + { + element.addEventListener(eventName, e => e.preventDefault(), { passive: false }); } }; window.ZBlazorDiagrams = s; diff --git a/src/Blazor.Diagrams/wwwroot/script.min.js b/src/Blazor.Diagrams/wwwroot/script.min.js index a4065277c..a900d0005 100644 --- a/src/Blazor.Diagrams/wwwroot/script.min.js +++ b/src/Blazor.Diagrams/wwwroot/script.min.js @@ -1 +1 @@ -var s={canvases:{},tracked:{},getBoundingClientRect:n=>n.getBoundingClientRect(),mo:new MutationObserver(()=>{for(id in s.canvases){const t=s.canvases[id],i=t.lastBounds,n=t.elem.getBoundingClientRect();(i.left!==n.left||i.top!==n.top||i.width!==n.width||i.height!==n.height)&&(t.lastBounds=n,t.ref.invokeMethodAsync("OnResize",n))}}),ro:new ResizeObserver(n=>{for(const t of n){let i=Array.from(t.target.attributes).find(n=>n.name.startsWith("_bl")).name.substring(4),n=s.tracked[i];n&&n.ref.invokeMethodAsync("OnResize",t.target.getBoundingClientRect())}}),observe:(n,t,i)=>{n&&(s.ro.observe(n),s.tracked[i]={ref:t},n.classList.contains("diagram-canvas")&&(s.canvases[i]={elem:n,ref:t,lastBounds:n.getBoundingClientRect()}))},unobserve:(n,t)=>{n&&s.ro.unobserve(n),delete s.tracked[t],delete s.canvases[t]}};window.ZBlazorDiagrams=s;window.addEventListener("scroll",()=>{for(id in s.canvases){const n=s.canvases[id];n.lastBounds=n.elem.getBoundingClientRect();n.ref.invokeMethodAsync("OnResize",n.lastBounds)}});s.mo.observe(document.body,{childList:!0,subtree:!0}); \ No newline at end of file +var s = { canvases: {}, tracked: {}, getBoundingClientRect: e => e.getBoundingClientRect(), mo: new MutationObserver((() => { for (id in s.canvases) { const e = s.canvases[id], t = e.lastBounds, n = e.elem.getBoundingClientRect(); t.left === n.left && t.top === n.top && t.width === n.width && t.height === n.height || (e.lastBounds = n, e.ref.invokeMethodAsync("OnResize", n)) } })), ro: new ResizeObserver((e => { for (const t of e) { let e = Array.from(t.target.attributes).find((e => e.name.startsWith("_bl"))).name.substring(4), n = s.tracked[e]; n && n.ref.invokeMethodAsync("OnResize", t.target.getBoundingClientRect()) } })), observe: (e, t, n) => { e && (s.ro.observe(e), s.tracked[n] = { ref: t }, e.classList.contains("diagram-canvas") && (s.canvases[n] = { elem: e, ref: t, lastBounds: e.getBoundingClientRect() })) }, unobserve: (e, t) => { e && s.ro.unobserve(e), delete s.tracked[t], delete s.canvases[t] }, addDefaultPreventingHandler: (e, s) => { e.addEventListener(s, (e => e.preventDefault()), { passive: !1 }) } }; window.ZBlazorDiagrams = s, window.addEventListener("scroll", (() => { for (id in s.canvases) { const e = s.canvases[id]; e.lastBounds = e.elem.getBoundingClientRect(), e.ref.invokeMethodAsync("OnResize", e.lastBounds) } })), s.mo.observe(document.body, { childList: !0, subtree: !0 }); \ No newline at end of file From c8dd3066652a3e5833b43cc18d289fff76faeb5e Mon Sep 17 00:00:00 2001 From: Shams Azam Date: Wed, 10 Jul 2024 09:50:12 +0530 Subject: [PATCH 14/17] enabled wheel preventing only for scroll behavior, other pr suggestions addressed --- site/Site/Pages/Documentation/Diagram/Behaviors.razor | 5 ++--- src/Blazor.Diagrams/Components/DiagramCanvas.razor.cs | 8 ++++++-- src/Blazor.Diagrams/Extensions/JSRuntimeExtensions.cs | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/site/Site/Pages/Documentation/Diagram/Behaviors.razor b/site/Site/Pages/Documentation/Diagram/Behaviors.razor index 4f3785adc..ff9a5f7d2 100644 --- a/site/Site/Pages/Documentation/Diagram/Behaviors.razor +++ b/site/Site/Pages/Documentation/Diagram/Behaviors.razor @@ -120,11 +120,10 @@ You can use the following ways to add different behaviors to the diagram.

Scroll Behavior

-

To scroll the diagram using the mouse wheel you can register the Scroll Behavior.

+

To scroll the diagram using the mouse wheel use ScrollBehavior.


-Diagram.UnregisterBehavior<WheelBehavior>();
-Diagram.RegisterBehavior(new ScrollBehavior(Diagram));
+_diagram.BehaviorOptions.DiagramWheelBehavior = _diagram.GetBehavior<ScrollBehavior>();
 
diff --git a/src/Blazor.Diagrams/Components/DiagramCanvas.razor.cs b/src/Blazor.Diagrams/Components/DiagramCanvas.razor.cs index f044ffe6e..c734b2168 100644 --- a/src/Blazor.Diagrams/Components/DiagramCanvas.razor.cs +++ b/src/Blazor.Diagrams/Components/DiagramCanvas.razor.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using Blazor.Diagrams.Core.Behaviors; using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Extensions; using Microsoft.AspNetCore.Components; @@ -62,7 +63,10 @@ protected override async Task OnAfterRenderAsync(bool firstRender) { BlazorDiagram.SetContainer(await JSRuntime.GetBoundingClientRect(elementReference)); await JSRuntime.ObserveResizes(elementReference, _reference!); - await JSRuntime.AddDefaultPreventingHandler(elementReference); + if (BlazorDiagram.GetBehavior() != null) + { + await JSRuntime.AddDefaultPreventingForWheelHandler(elementReference); + } } } @@ -100,7 +104,7 @@ private void OnKeyDown(KeyboardEventArgs e) BlazorDiagram.TriggerKeyDown(e.ToCore()); } - private async void OnWheel(WheelEventArgs e) + private void OnWheel(WheelEventArgs e) { BlazorDiagram.TriggerWheel(e.ToCore()); } diff --git a/src/Blazor.Diagrams/Extensions/JSRuntimeExtensions.cs b/src/Blazor.Diagrams/Extensions/JSRuntimeExtensions.cs index c11886223..5509f7428 100644 --- a/src/Blazor.Diagrams/Extensions/JSRuntimeExtensions.cs +++ b/src/Blazor.Diagrams/Extensions/JSRuntimeExtensions.cs @@ -31,7 +31,7 @@ public static async Task UnobserveResizes(this IJSRuntime jsRuntime, ElementRefe await jsRuntime.InvokeVoidAsync("ZBlazorDiagrams.unobserve", element, element.Id); } - public static async Task AddDefaultPreventingHandler(this IJSRuntime jsRuntime, ElementReference element) + public static async Task AddDefaultPreventingForWheelHandler(this IJSRuntime jsRuntime, ElementReference element) { await jsRuntime.InvokeVoidAsync("ZBlazorDiagrams.addDefaultPreventingHandler", element, "wheel"); } From 0e181689de69101a8d67be86151d219a08741067 Mon Sep 17 00:00:00 2001 From: Shams Azam Date: Wed, 10 Jul 2024 10:29:24 +0530 Subject: [PATCH 15/17] fixed scroll behavior checking for preventing default wheel behavior --- src/Blazor.Diagrams/Components/DiagramCanvas.razor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Blazor.Diagrams/Components/DiagramCanvas.razor.cs b/src/Blazor.Diagrams/Components/DiagramCanvas.razor.cs index c734b2168..bf20a7e07 100644 --- a/src/Blazor.Diagrams/Components/DiagramCanvas.razor.cs +++ b/src/Blazor.Diagrams/Components/DiagramCanvas.razor.cs @@ -63,7 +63,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) { BlazorDiagram.SetContainer(await JSRuntime.GetBoundingClientRect(elementReference)); await JSRuntime.ObserveResizes(elementReference, _reference!); - if (BlazorDiagram.GetBehavior() != null) + if (BlazorDiagram.BehaviorOptions.DiagramWheelBehavior is ScrollBehavior) { await JSRuntime.AddDefaultPreventingForWheelHandler(elementReference); } From 9d32e0730d8b8000455ef7780ae175b19550677c Mon Sep 17 00:00:00 2001 From: Shams Azam Date: Thu, 11 Jul 2024 11:38:23 +0530 Subject: [PATCH 16/17] updated documentation for BehaviorOptions. --- site/Site/Pages/Documentation/Diagram/Behaviors.razor | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/site/Site/Pages/Documentation/Diagram/Behaviors.razor b/site/Site/Pages/Documentation/Diagram/Behaviors.razor index ff9a5f7d2..094b33112 100644 --- a/site/Site/Pages/Documentation/Diagram/Behaviors.razor +++ b/site/Site/Pages/Documentation/Diagram/Behaviors.razor @@ -114,13 +114,14 @@ Diagram.UnregisterBehavior<SelectionBehavior>(); Diagram.RegisterBehavior(new MySelectionBehavior(Diagram)); -

Using Different Behaviors

+

Configure behaviors for different actions on input

-You can use the following ways to add different behaviors to the diagram. +You can configure a behavior to perform different actions for an input. Such as scrolling a diagram on mouse wheel instead of zooming in and out. +This can be done using the BehaviorOptions. See the below example. -

Scroll Behavior

+

Scrolling a diagram on mouse wheel

-

To scroll the diagram using the mouse wheel use ScrollBehavior.

+

To scroll a diagram using the mouse wheel set the DiagramWheelBehavior property of BehaviorOptions to use ScrollBehavior.


 _diagram.BehaviorOptions.DiagramWheelBehavior = _diagram.GetBehavior<ScrollBehavior>();

From 742b17d81093d16408602f8c3c6851d339866865 Mon Sep 17 00:00:00 2001
From: Shams Azam 
Date: Thu, 18 Jul 2024 15:56:03 +0530
Subject: [PATCH 17/17] fixed identation

---
 src/Blazor.Diagrams.Core/Diagram.cs | 48 ++++++++++++++---------------
 1 file changed, 24 insertions(+), 24 deletions(-)

diff --git a/src/Blazor.Diagrams.Core/Diagram.cs b/src/Blazor.Diagrams.Core/Diagram.cs
index e63e832e7..5f7abba6c 100644
--- a/src/Blazor.Diagrams.Core/Diagram.cs
+++ b/src/Blazor.Diagrams.Core/Diagram.cs
@@ -44,11 +44,11 @@ protected Diagram()
         _behaviors = new Dictionary();
         _orderedSelectables = new List();
 
-            Nodes = new NodeLayer(this);
-            Links = new LinkLayer(this);
-            Groups = new GroupLayer(this);
-            Controls = new ControlsLayer();
-            BehaviorOptions = new DiagramBehaviorOptions();
+        Nodes = new NodeLayer(this);
+        Links = new LinkLayer(this);
+        Groups = new GroupLayer(this);
+        Controls = new ControlsLayer();
+        BehaviorOptions = new DiagramBehaviorOptions();
 
         Nodes.Added += OnSelectableAdded;
         Links.Added += OnSelectableAdded;
@@ -169,26 +169,26 @@ public void UnselectAll()
 
     #region Behaviors
 
-        void RegisterDefaultBehaviors()
-        {
-            RegisterBehavior(new SelectionBehavior(this));
-            RegisterBehavior(new DragMovablesBehavior(this));
-            RegisterBehavior(new DragNewLinkBehavior(this));
-            RegisterBehavior(new PanBehavior(this));
-            RegisterBehavior(new ZoomBehavior(this));
-            RegisterBehavior(new EventsBehavior(this));
-            RegisterBehavior(new KeyboardShortcutsBehavior(this));
-            RegisterBehavior(new ControlsBehavior(this));
-            RegisterBehavior(new VirtualizationBehavior(this));
-            RegisterBehavior(new ScrollBehavior(this));
-            RegisterBehavior(new SelectionBoxBehavior(this));
-        }
+    void RegisterDefaultBehaviors()
+    {
+        RegisterBehavior(new SelectionBehavior(this));
+        RegisterBehavior(new DragMovablesBehavior(this));
+        RegisterBehavior(new DragNewLinkBehavior(this));
+        RegisterBehavior(new PanBehavior(this));
+        RegisterBehavior(new ZoomBehavior(this));
+        RegisterBehavior(new EventsBehavior(this));
+        RegisterBehavior(new KeyboardShortcutsBehavior(this));
+        RegisterBehavior(new ControlsBehavior(this));
+        RegisterBehavior(new VirtualizationBehavior(this));
+        RegisterBehavior(new ScrollBehavior(this));
+        RegisterBehavior(new SelectionBoxBehavior(this));
+    }
 
-        public void RegisterBehavior(Behavior behavior)
-        {
-            var type = behavior.GetType();
-            if (_behaviors.ContainsKey(type))
-                throw new Exception($"Behavior '{type.Name}' already registered");
+    public void RegisterBehavior(Behavior behavior)
+    {
+        var type = behavior.GetType();
+        if (_behaviors.ContainsKey(type))
+            throw new Exception($"Behavior '{type.Name}' already registered");
 
         _behaviors.Add(type, behavior);
     }