From baaec9cef0d6ea9b018c5fb7e22ede9b80980fb0 Mon Sep 17 00:00:00 2001 From: zHaytam Date: Sun, 22 Aug 2021 11:18:42 +0100 Subject: [PATCH 01/10] feat: MouseDoubleClick event --- samples/SharedDemo/Demos/Events.razor.cs | 6 ++++++ .../Behaviors/EventsBehavior.cs | 15 +++++++++++++++ src/Blazor.Diagrams.Core/Diagram.cs | 7 +++++++ 3 files changed, 28 insertions(+) diff --git a/samples/SharedDemo/Demos/Events.razor.cs b/samples/SharedDemo/Demos/Events.razor.cs index 8aed84be..d83cfa26 100644 --- a/samples/SharedDemo/Demos/Events.razor.cs +++ b/samples/SharedDemo/Demos/Events.razor.cs @@ -73,6 +73,12 @@ private void RegisterEvents() events.Add($"MouseClick, Type={m?.GetType().Name}, ModelId={m?.Id}"); StateHasChanged(); }; + + diagram.MouseDoubleClick += (m, e) => + { + events.Add($"MouseDoubleClick, Type={m?.GetType().Name}, ModelId={m?.Id}"); + StateHasChanged(); + }; } private NodeModel NewNode(double x, double y) diff --git a/src/Blazor.Diagrams.Core/Behaviors/EventsBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/EventsBehavior.cs index ba6fe5fe..9a1c6fb5 100644 --- a/src/Blazor.Diagrams.Core/Behaviors/EventsBehavior.cs +++ b/src/Blazor.Diagrams.Core/Behaviors/EventsBehavior.cs @@ -1,19 +1,34 @@ using Blazor.Diagrams.Core.Models.Base; using Microsoft.AspNetCore.Components.Web; using System; +using System.Diagnostics; namespace Blazor.Diagrams.Core.Behaviors { public class EventsBehavior : Behavior { + private readonly Stopwatch _mouseClickSw; private bool _captureMouseMove; private int _mouseMovedCount; public EventsBehavior(Diagram diagram) : base(diagram) { + _mouseClickSw = new Stopwatch(); + Diagram.MouseDown += OnMouseDown; Diagram.MouseMove += OnMouseMove; Diagram.MouseUp += OnMouseUp; + Diagram.MouseClick += OnMouseClick; + } + + private void OnMouseClick(Model model, MouseEventArgs e) + { + if (_mouseClickSw.IsRunning && _mouseClickSw.ElapsedMilliseconds <= 500) + { + Diagram.OnMouseDoubleClick(model, e); + } + + _mouseClickSw.Restart(); } private void OnMouseDown(Model model, MouseEventArgs e) diff --git a/src/Blazor.Diagrams.Core/Diagram.cs b/src/Blazor.Diagrams.Core/Diagram.cs index 73da83b0..da15f0a6 100644 --- a/src/Blazor.Diagrams.Core/Diagram.cs +++ b/src/Blazor.Diagrams.Core/Diagram.cs @@ -27,6 +27,7 @@ public class Diagram : Model public event Action? KeyDown; public event Action? Wheel; public event Action? MouseClick; + public event Action? MouseDoubleClick; public event Action? TouchStart; public event Action? TouchMove; public event Action? TouchEnd; @@ -341,6 +342,8 @@ public Point GetRelativePoint(double clientX, double clientY) return new Point(clientX - Container.Left, clientY - Container.Top); } + #region Events + internal void OnMouseDown(Model model, MouseEventArgs e) => MouseDown?.Invoke(model, e); internal void OnMouseMove(Model model, MouseEventArgs e) => MouseMove?.Invoke(model, e); @@ -353,10 +356,14 @@ public Point GetRelativePoint(double clientX, double clientY) internal void OnMouseClick(Model model, MouseEventArgs e) => MouseClick?.Invoke(model, e); + internal void OnMouseDoubleClick(Model model, MouseEventArgs e) => MouseDoubleClick?.Invoke(model, e); + internal void OnTouchStart(Model model, TouchEventArgs e) => TouchStart?.Invoke(model, e); internal void OnTouchMove(Model model, TouchEventArgs e) => TouchMove?.Invoke(model, e); internal void OnTouchEnd(Model model, TouchEventArgs e) => TouchEnd?.Invoke(model, e); + + #endregion } } From 57655cf532f39fd22a8d49de1e1a2c48c5f75422 Mon Sep 17 00:00:00 2001 From: zHaytam Date: Sun, 22 Aug 2021 12:58:27 +0100 Subject: [PATCH 02/10] tests: EventsBehavior --- .../Behaviors/EventsBehaviorTests.cs | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 tests/Blazor.Diagrams.Core.Tests/Behaviors/EventsBehaviorTests.cs diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/EventsBehaviorTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/EventsBehaviorTests.cs new file mode 100644 index 00000000..6a87456c --- /dev/null +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/EventsBehaviorTests.cs @@ -0,0 +1,94 @@ +using Blazor.Diagrams.Core.Behaviors; +using FluentAssertions; +using Microsoft.AspNetCore.Components.Web; +using System.Threading.Tasks; +using Xunit; + +namespace Blazor.Diagrams.Core.Tests.Behaviors +{ + public class EventsBehaviorTests + { + [Fact] + public void Behavior_ShouldNotTriggerMouseClick_WhenItsRemoved() + { + // Arrange + var diagram = new Diagram(); + diagram.UnregisterBehavior(); + var eventTriggered = false; + + // Act + diagram.MouseClick += (m, e) => eventTriggered = true; + diagram.OnMouseDown(null, new MouseEventArgs()); + diagram.OnMouseUp(null, new MouseEventArgs()); + + // Assert + eventTriggered.Should().BeFalse(); + } + + [Fact] + public void Behavior_ShouldTriggerMouseClick_WhenMouseDownThenUpWithoutMove() + { + // Arrange + var diagram = new Diagram(); + var eventTriggered = false; + + // Act + diagram.MouseClick += (m, e) => eventTriggered = true; + diagram.OnMouseDown(null, new MouseEventArgs()); + diagram.OnMouseUp(null, new MouseEventArgs()); + + // Assert + eventTriggered.Should().BeTrue(); + } + + [Fact] + public void Behavior_ShouldNotTriggerMouseClick_WhenMouseMoves() + { + // Arrange + var diagram = new Diagram(); + var eventTriggered = false; + + // Act + diagram.MouseClick += (m, e) => eventTriggered = true; + diagram.OnMouseDown(null, new MouseEventArgs()); + diagram.OnMouseMove(null, new MouseEventArgs()); + diagram.OnMouseUp(null, new MouseEventArgs()); + + // Assert + eventTriggered.Should().BeFalse(); + } + + [Fact] + public void Behavior_ShouldTriggerMouseDoubleClick_WhenTwoMouseClicksHappenWithinTime() + { + // Arrange + var diagram = new Diagram(); + var eventTriggered = false; + + // Act + diagram.MouseDoubleClick += (m, e) => eventTriggered = true; + diagram.OnMouseClick(null, new MouseEventArgs()); + diagram.OnMouseClick(null, new MouseEventArgs()); + + // Assert + eventTriggered.Should().BeTrue(); + } + + [Fact] + public async Task Behavior_ShouldNotTriggerMouseDoubleClick_WhenTimeExceeds500() + { + // Arrange + var diagram = new Diagram(); + var eventTriggered = false; + + // Act + diagram.MouseDoubleClick += (m, e) => eventTriggered = true; + diagram.OnMouseClick(null, new MouseEventArgs()); + await Task.Delay(520); + diagram.OnMouseClick(null, new MouseEventArgs()); + + // Assert + eventTriggered.Should().BeFalse(); + } + } +} From 78c01564c34f540d672c233f0597029960a2760d Mon Sep 17 00:00:00 2001 From: zHaytam Date: Sun, 22 Aug 2021 17:54:31 +0100 Subject: [PATCH 03/10] feat: GetScreenPoint to get screen coords from diagram coords --- src/Blazor.Diagrams.Core/Diagram.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Blazor.Diagrams.Core/Diagram.cs b/src/Blazor.Diagrams.Core/Diagram.cs index da15f0a6..a83958cc 100644 --- a/src/Blazor.Diagrams.Core/Diagram.cs +++ b/src/Blazor.Diagrams.Core/Diagram.cs @@ -342,6 +342,14 @@ public Point GetRelativePoint(double clientX, double clientY) return new Point(clientX - Container.Left, clientY - Container.Top); } + public Point GetScreenPoint(double clientX, double clientY) + { + if (Container == null) + throw new Exception("Container not available. Make sure you're not using this method before the diagram is fully loaded"); + + return new Point(Zoom * clientX + Container.Left + Pan.X, Zoom * clientY + Container.Top + Pan.Y); + } + #region Events internal void OnMouseDown(Model model, MouseEventArgs e) => MouseDown?.Invoke(model, e); From 0c3dcf81939a137d6131e6801384c819c615823a Mon Sep 17 00:00:00 2001 From: zHaytam Date: Sun, 22 Aug 2021 20:21:37 +0100 Subject: [PATCH 04/10] tests: GetScreenPoint --- .../DiagramTests.cs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tests/Blazor.Diagrams.Core.Tests/DiagramTests.cs diff --git a/tests/Blazor.Diagrams.Core.Tests/DiagramTests.cs b/tests/Blazor.Diagrams.Core.Tests/DiagramTests.cs new file mode 100644 index 00000000..aeca243e --- /dev/null +++ b/tests/Blazor.Diagrams.Core.Tests/DiagramTests.cs @@ -0,0 +1,26 @@ +using Blazor.Diagrams.Core.Geometry; +using FluentAssertions; +using Xunit; + +namespace Blazor.Diagrams.Core.Tests +{ + public class DiagramTests + { + [Fact] + public void GetScreenPoint_ShouldReturnCorrectPoint() + { + // Arrange + var diagram = new Diagram(); + + // Act + diagram.SetZoom(1.234); + diagram.UpdatePan(50, 50); + diagram.SetContainer(new Rectangle(30, 65, 1000, 793)); + var pt = diagram.GetScreenPoint(100, 200); + + // Assert + pt.X.Should().Be(203.4); // 2*X + panX + left + pt.Y.Should().Be(361.8); // 2*Y + panY + top + } + } +} From 9f4c9be6c5109f47c3540d0097a015ead03e8aa4 Mon Sep 17 00:00:00 2001 From: zHaytam Date: Mon, 23 Aug 2021 09:04:45 +0100 Subject: [PATCH 05/10] fix: ZoomChanged not triggered in ZoomToFit --- src/Blazor.Diagrams.Core/Diagram.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Blazor.Diagrams.Core/Diagram.cs b/src/Blazor.Diagrams.Core/Diagram.cs index a83958cc..a3795097 100644 --- a/src/Blazor.Diagrams.Core/Diagram.cs +++ b/src/Blazor.Diagrams.Core/Diagram.cs @@ -295,11 +295,15 @@ public void ZoomToFit(double margin = 10) var xf = Container.Width / width; var yf = Container.Height / height; - Zoom = Math.Min(xf, yf); var nx = Container.Left + Pan.X + minX * Zoom; var ny = Container.Top + Pan.Y + minY * Zoom; + + SuspendRefresh = true; + SetZoom(Math.Min(xf, yf)); UpdatePan(Container.Left - nx, Container.Top - ny); + SuspendRefresh = false; + Refresh(); } public void UpdatePan(double deltaX, double deltaY) From f53b44c7eaee49ffd0797cc37e7174b22d800812 Mon Sep 17 00:00:00 2001 From: zHaytam Date: Mon, 23 Aug 2021 20:45:55 +0100 Subject: [PATCH 06/10] tests: ZoomToFit --- .../DiagramTests.cs | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/tests/Blazor.Diagrams.Core.Tests/DiagramTests.cs b/tests/Blazor.Diagrams.Core.Tests/DiagramTests.cs index aeca243e..44079e78 100644 --- a/tests/Blazor.Diagrams.Core.Tests/DiagramTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/DiagramTests.cs @@ -1,4 +1,5 @@ using Blazor.Diagrams.Core.Geometry; +using Blazor.Diagrams.Core.Models; using FluentAssertions; using Xunit; @@ -22,5 +23,73 @@ public void GetScreenPoint_ShouldReturnCorrectPoint() pt.X.Should().Be(203.4); // 2*X + panX + left pt.Y.Should().Be(361.8); // 2*Y + panY + top } + + [Fact] + public void ZoomToFit_ShouldUseSelectedNodesIfAny() + { + // Arrange + var diagram = new Diagram(); + diagram.SetContainer(new Rectangle(new Point(0, 0), new Size(1080, 768))); + diagram.Nodes.Add(new NodeModel(new Point(50, 50)) + { + Size = new Size(100, 80) + }); + diagram.SelectModel(diagram.Nodes[0], true); + + // Act + diagram.ZoomToFit(10); + + // Assert + diagram.Zoom.Should().BeApproximately(7.68, 0.001); + diagram.Pan.X.Should().Be(-40); + diagram.Pan.Y.Should().Be(-40); + } + + [Fact] + public void ZoomToFit_ShouldUseNodesWhenNoneSelected() + { + // Arrange + var diagram = new Diagram(); + diagram.SetContainer(new Rectangle(new Point(0, 0), new Size(1080, 768))); + diagram.Nodes.Add(new NodeModel(new Point(50, 50)) + { + Size = new Size(100, 80) + }); + + // Act + diagram.ZoomToFit(10); + + // Assert + diagram.Zoom.Should().BeApproximately(7.68, 0.001); + diagram.Pan.X.Should().Be(-40); + diagram.Pan.Y.Should().Be(-40); + } + + [Fact] + public void ZoomToFit_ShouldTriggerAppropriateEvents() + { + // Arrange + var diagram = new Diagram(); + diagram.SetContainer(new Rectangle(new Point(0, 0), new Size(1080, 768))); + diagram.Nodes.Add(new NodeModel(new Point(50, 50)) + { + Size = new Size(100, 80) + }); + + var refreshes = 0; + var zoomChanges = 0; + var panChanges = 0; + + // Act + diagram.Changed += () => refreshes++; + diagram.ZoomChanged += () => zoomChanges++; + diagram.PanChanged += () => panChanges++; + diagram.ZoomToFit(10); + + // Assert + refreshes.Should().Be(1); + zoomChanges.Should().Be(1); + panChanges.Should().Be(1); + } } } From 0589c15f77692ec540d7d9fdaa37d367305dd9d1 Mon Sep 17 00:00:00 2001 From: zHaytam Date: Sat, 28 Aug 2021 15:15:09 +0100 Subject: [PATCH 07/10] feat: Title property in nodes --- src/Blazor.Diagrams.Core/Models/NodeModel.cs | 1 + src/Blazor.Diagrams/Components/NodeWidget.razor | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Blazor.Diagrams.Core/Models/NodeModel.cs b/src/Blazor.Diagrams.Core/Models/NodeModel.cs index ed305009..b01d8d0b 100644 --- a/src/Blazor.Diagrams.Core/Models/NodeModel.cs +++ b/src/Blazor.Diagrams.Core/Models/NodeModel.cs @@ -44,6 +44,7 @@ public Size? Size } } public GroupModel? Group { get; internal set; } + public string Title { get; set; } public IReadOnlyList Ports => _ports; public IReadOnlyList Links => _links; diff --git a/src/Blazor.Diagrams/Components/NodeWidget.razor b/src/Blazor.Diagrams/Components/NodeWidget.razor index b99a0bb9..25c6515b 100644 --- a/src/Blazor.Diagrams/Components/NodeWidget.razor +++ b/src/Blazor.Diagrams/Components/NodeWidget.razor @@ -1,5 +1,5 @@ 
- Node Title + @(Node.Title ?? "Title") @foreach (var port in Node.Ports) { From f1c0e299fe19be2f4ae502c0f1f47dd46d6a9aaf Mon Sep 17 00:00:00 2001 From: zHaytam Date: Sat, 28 Aug 2021 15:26:10 +0100 Subject: [PATCH 08/10] fix: SourceNode and TargetNode not being set when ports change in link --- src/Blazor.Diagrams.Core/Models/Base/BaseLinkModel.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Blazor.Diagrams.Core/Models/Base/BaseLinkModel.cs b/src/Blazor.Diagrams.Core/Models/Base/BaseLinkModel.cs index 31a569f8..2a898a51 100644 --- a/src/Blazor.Diagrams.Core/Models/Base/BaseLinkModel.cs +++ b/src/Blazor.Diagrams.Core/Models/Base/BaseLinkModel.cs @@ -43,8 +43,8 @@ public BaseLinkModel(string id, PortModel sourcePort, PortModel? targetPort = nu TargetNode = targetPort?.Parent; } - public NodeModel SourceNode { get; } - public NodeModel? TargetNode { get; } + public NodeModel SourceNode { get; private set; } + public NodeModel? TargetNode { get; private set; } public PortModel? SourcePort { get; private set; } public PortModel? TargetPort { get; private set; } public bool IsAttached => TargetNode != null || TargetPort != null; @@ -67,6 +67,7 @@ public void SetSourcePort(PortModel port) SourcePort?.RemoveLink(this); SourcePort = port; SourcePort.AddLink(this); + SourceNode = SourcePort.Parent; SourcePortChanged?.Invoke(this, old, SourcePort); } @@ -79,6 +80,7 @@ public void SetTargetPort(PortModel? port) TargetPort?.RemoveLink(this); TargetPort = port; TargetPort?.AddLink(this); + TargetNode = TargetPort?.Parent; TargetPortChanged?.Invoke(this, old, TargetPort); } } From 1866a0db40e6559349dace0eba62ba8c5b3af394 Mon Sep 17 00:00:00 2001 From: zHaytam Date: Sat, 28 Aug 2021 15:43:45 +0100 Subject: [PATCH 09/10] tests: BaseLinkModel --- ZBD_Title.png | Bin 0 -> 65780 bytes .../Models/Base/BaseLinkModelTests.cs | 93 ++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 ZBD_Title.png create mode 100644 tests/Blazor.Diagrams.Core.Tests/Models/Base/BaseLinkModelTests.cs diff --git a/ZBD_Title.png b/ZBD_Title.png new file mode 100644 index 0000000000000000000000000000000000000000..6b14569142b9717a79dc4ccb85f15fa9b86ad2d9 GIT binary patch literal 65780 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 + { + eventsTriggered++; + linkInstance = l; + oldSp = o; + newSp = n; + }; + + link.SetSourcePort(sp); + + // Assert + eventsTriggered.Should().Be(1); + link.SourcePort.Should().BeSameAs(sp); + oldSp.Should().NotBeNull(); + newSp.Should().BeSameAs(sp); + linkInstance.Should().BeSameAs(link); + link.SourceNode.Should().BeSameAs(parent); + } + + [Fact] + public void SetTargetPort_ShouldChangePropertiesAndTriggerEvent() + { + // Arrange + var link = new TestLink(sourcePort: new PortModel(null), targetPort: null); + var parent = new NodeModel(); + var tp = new PortModel(parent); + var eventsTriggered = 0; + PortModel oldTp = null; + PortModel newTp = null; + BaseLinkModel linkInstance = null; + + // Act + link.TargetPortChanged += (l, o, n) => + { + eventsTriggered++; + linkInstance = l; + oldTp = o; + newTp = n; + }; + + link.SetTargetPort(tp); + + // Assert + eventsTriggered.Should().Be(1); + link.TargetPort.Should().BeSameAs(tp); + oldTp.Should().BeNull(); + newTp.Should().BeSameAs(tp); + linkInstance.Should().BeSameAs(link); + link.TargetNode.Should().BeSameAs(parent); + } + + private class TestLink : BaseLinkModel + { + public TestLink(NodeModel sourceNode, NodeModel targetNode) : base(sourceNode, targetNode) + { + } + + public TestLink(PortModel sourcePort, PortModel targetPort = null) : base(sourcePort, targetPort) + { + } + + public TestLink(string id, NodeModel sourceNode, NodeModel targetNode) : base(id, sourceNode, targetNode) + { + } + + public TestLink(string id, PortModel sourcePort, PortModel targetPort = null) : base(id, sourcePort, targetPort) + { + } + } + } +} From aa1e963e2bf5ef5f8914c82d4c454e640d3cf3fb Mon Sep 17 00:00:00 2001 From: zHaytam Date: Sun, 29 Aug 2021 11:18:37 +0100 Subject: [PATCH 10/10] Update Versions, CHANGELOG & README --- CHANGELOG.md | 13 +++++++++++++ README.md | 7 ++++++- .../Blazor.Diagrams.Core.csproj | 6 +++--- src/Blazor.Diagrams/Blazor.Diagrams.csproj | 6 +++--- 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d3a6d02..c0301195 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Diagrams (2.1.4) - 2021-08-29 + +### Added + +- `MouseDoubleClick` (500ms interval) event in `Diagram`. +- `GetScreenPoint` in `Diagram` in order to get the screen points from a diagram point (e.g. node position). +- `Title` property in `NodeModel`, used by the default node widget. + +### Fixed + +- `ZoomToFit` not triggering `ZoomChanged` event. +- `SourceNode` and `TargetNode` not being set in `BaseLinkModel` when the ports change. + ## Diagrams (2.1.3) - 2021-07-19 ### Added diff --git a/README.md b/README.md index 3ac8d4a6..dcd2df3c 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,11 @@ Repository: https://github.com/Blazor-Diagrams/Blazor.DatabaseDesigner ![](DBDesigner.png) +### Contributing + +All kinds of contributions are welcome! +If you're interested in helping, please create an issue or comment on an existing one to explain what you will be doing. This is because multiple people can be working on the same problem. + ## Feedback -If you find a bug or you want to see a functionality in this library, feel free to open an issue. All kinds of contributions are welcome! +If you find a bug or you want to see a functionality in this library, feel free to open an issue. diff --git a/src/Blazor.Diagrams.Core/Blazor.Diagrams.Core.csproj b/src/Blazor.Diagrams.Core/Blazor.Diagrams.Core.csproj index b6fb2f98..5b5abb51 100644 --- a/src/Blazor.Diagrams.Core/Blazor.Diagrams.Core.csproj +++ b/src/Blazor.Diagrams.Core/Blazor.Diagrams.Core.csproj @@ -7,10 +7,10 @@ MIT zHaytam A fully customizable and extensible all-purpose diagrams library for Blazor - 2.1.3 - 2.1.3 + 2.1.4 + 2.1.4 https://github.com/zHaytam/Blazor.Diagrams - 2.1.3 + 2.1.4 Z.Blazor.Diagrams.Core blazor diagrams diagramming svg drag Z.Blazor.Diagrams.Core diff --git a/src/Blazor.Diagrams/Blazor.Diagrams.csproj b/src/Blazor.Diagrams/Blazor.Diagrams.csproj index 170a3be5..dc2dcd1a 100644 --- a/src/Blazor.Diagrams/Blazor.Diagrams.csproj +++ b/src/Blazor.Diagrams/Blazor.Diagrams.csproj @@ -5,11 +5,11 @@ 3.0 zHaytam MIT - 2.1.3 - 2.1.3 + 2.1.4 + 2.1.4 https://github.com/zHaytam/Blazor.Diagrams A fully customizable and extensible all-purpose diagrams library for Blazor - 2.1.3 + 2.1.4 true blazor diagrams diagramming svg drag Z.Blazor.Diagrams