@(Node.Title ?? "Title")
@foreach (var port in Node.Ports)
{
@@ -11,4 +11,12 @@
[Parameter]
public NodeModel Node { get; set; } = null!;
+ private string GenerateStyle()
+ {
+ if (Node.Size is not null)
+ {
+ return $"width: {Node.Size.Width}px; height: {Node.Size.Height}px";
+ }
+ return string.Empty;
+ }
}
\ No newline at end of file
diff --git a/src/Blazor.Diagrams/wwwroot/default.styles.css b/src/Blazor.Diagrams/wwwroot/default.styles.css
index b095bbe4e..2b355029a 100644
--- a/src/Blazor.Diagrams/wwwroot/default.styles.css
+++ b/src/Blazor.Diagrams/wwwroot/default.styles.css
@@ -127,4 +127,28 @@ g.diagram-group.default.selected > rect {
transform: translate(-50%, -50%);
}
+.default-node-resizer {
+ width: 5px;
+ height: 5px;
+ background-color: #f5f5f5;
+ border: 1px solid #6e9fd4;
+ position: absolute;
+}
+
+.default-node-resizer.bottomright {
+ cursor: nwse-resize;
+}
+
+.default-node-resizer.topright {
+ cursor: nesw-resize;
+}
+
+.default-node-resizer.bottomleft {
+ cursor: nesw-resize;
+}
+
+.default-node-resizer.topleft {
+ cursor: nwse-resize;
+}
+
/*# sourceMappingURL=wwwroot\default.styles.css.map */
diff --git a/src/Blazor.Diagrams/wwwroot/default.styles.min.css b/src/Blazor.Diagrams/wwwroot/default.styles.min.css
index c44adedc3..e794e823e 100644
--- a/src/Blazor.Diagrams/wwwroot/default.styles.min.css
+++ b/src/Blazor.Diagrams/wwwroot/default.styles.min.css
@@ -1 +1 @@
-.default-node{width:100px;height:80px;border-radius:10px;background-color:#f5f5f5;border:1px solid #e8e8e8;-webkit-box-shadow:0 2px 1px -1px rgba(0,0,0,.2),0 1px 1px 0 rgba(0,0,0,.14),0 1px 3px 0 rgba(0,0,0,.12);box-shadow:0 2px 1px -1px rgba(0,0,0,.2),0 1px 1px 0 rgba(0,0,0,.14),0 1px 3px 0 rgba(0,0,0,.12);position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;}.default-node.selected{border:1px solid #6e9fd4;}.default-node.selected .diagram-port{border:1px solid #6e9fd4;}.default-node .diagram-port,.default.diagram-group .diagram-port{width:20px;height:20px;margin:-10px;border-radius:50%;background-color:#f5f5f5;border:1px solid #d4d4d4;cursor:pointer;position:absolute;}.default-node .diagram-port:hover,.default-node .diagram-port.has-links,.default.diagram-group .diagram-port.has-links{background-color:#000;}.default-node .diagram-port.bottom,.default.diagram-group .diagram-port.bottom{bottom:0;left:50%;}.default-node .diagram-port.bottomleft,.default.diagram-group .diagram-port.bottomleft{bottom:0;left:0;}.default-node .diagram-port.bottomright,.default.diagram-group .diagram-port.bottomright{bottom:0;right:0;}.default-node .diagram-port.top,.default.diagram-group .diagram-port.top{top:0;left:50%;}.default-node .diagram-port.topleft,.default.diagram-group .diagram-port.topleft{top:0;left:0;}.default-node .diagram-port.topright,.default.diagram-group .diagram-port.topright{top:0;right:0;}.default-node .diagram-port.left,.default.diagram-group .diagram-port.left{left:0;top:50%;}.default-node .diagram-port.right,.default.diagram-group .diagram-port.right{right:0;top:50%;}.diagram-navigator.default{position:absolute;bottom:10px;right:10px;border:3px solid #9ba8b0;border-radius:15px;padding:20px;background-color:#fff;}div.diagram-group.default{outline:2px solid #000;background:#c6c6c6;}div.diagram-group.default.selected{outline:2px solid #6e9fd4;}g.diagram-group.default rect{outline:2px solid #000;fill:#c6c632;}g.diagram-group.default.selected>rect{outline:2px solid #008000;}.diagram-link div.default-link-label{display:inline-block;color:#fff;background-color:#6e9fd4;border-radius:.25rem;padding:.25rem;text-align:center;font-size:.875rem;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;min-width:3rem;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%);}
\ No newline at end of file
+.default-node{width:100px;height:80px;border-radius:10px;background-color:#f5f5f5;border:1px solid #e8e8e8;-webkit-box-shadow:0 2px 1px -1px rgba(0,0,0,.2),0 1px 1px 0 rgba(0,0,0,.14),0 1px 3px 0 rgba(0,0,0,.12);box-shadow:0 2px 1px -1px rgba(0,0,0,.2),0 1px 1px 0 rgba(0,0,0,.14),0 1px 3px 0 rgba(0,0,0,.12);position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;}.default-node.selected{border:1px solid #6e9fd4;}.default-node.selected .diagram-port{border:1px solid #6e9fd4;}.default-node .diagram-port,.default.diagram-group .diagram-port{width:20px;height:20px;margin:-10px;border-radius:50%;background-color:#f5f5f5;border:1px solid #d4d4d4;cursor:pointer;position:absolute;}.default-node .diagram-port:hover,.default-node .diagram-port.has-links,.default.diagram-group .diagram-port.has-links{background-color:#000;}.default-node .diagram-port.bottom,.default.diagram-group .diagram-port.bottom{bottom:0;left:50%;}.default-node .diagram-port.bottomleft,.default.diagram-group .diagram-port.bottomleft{bottom:0;left:0;}.default-node .diagram-port.bottomright,.default.diagram-group .diagram-port.bottomright{bottom:0;right:0;}.default-node .diagram-port.top,.default.diagram-group .diagram-port.top{top:0;left:50%;}.default-node .diagram-port.topleft,.default.diagram-group .diagram-port.topleft{top:0;left:0;}.default-node .diagram-port.topright,.default.diagram-group .diagram-port.topright{top:0;right:0;}.default-node .diagram-port.left,.default.diagram-group .diagram-port.left{left:0;top:50%;}.default-node .diagram-port.right,.default.diagram-group .diagram-port.right{right:0;top:50%;}.diagram-navigator.default{position:absolute;bottom:10px;right:10px;border:3px solid #9ba8b0;border-radius:15px;padding:20px;background-color:#fff;}div.diagram-group.default{outline:2px solid #000;background:#c6c6c6;}div.diagram-group.default.selected{outline:2px solid #6e9fd4;}g.diagram-group.default rect{outline:2px solid #000;fill:#c6c632;}g.diagram-group.default.selected>rect{outline:2px solid #008000;}.diagram-link div.default-link-label{display:inline-block;color:#fff;background-color:#6e9fd4;border-radius:.25rem;padding:.25rem;text-align:center;font-size:.875rem;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;min-width:3rem;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%);}.default-node-resizer{width:5px;height:5px;background-color:#f5f5f5;border:1px solid #6e9fd4;position:absolute;}.default-node-resizer.bottomright{cursor:nwse-resize;}.default-node-resizer.topright{cursor:nesw-resize;}.default-node-resizer.bottomleft{cursor:nesw-resize;}.default-node-resizer.topleft{cursor:nwse-resize;}
\ No newline at end of file
diff --git a/src/Blazor.Diagrams/wwwroot/default.styles.min.css.gz b/src/Blazor.Diagrams/wwwroot/default.styles.min.css.gz
index 905f20cd3084e4807fd8feb323b3f30ca017d835..3c43a8a10a61907cb9619cdbdc3efc83f8d13ceb 100644
GIT binary patch
literal 735
zcmV<50wDb#iwFP!000003bj^kj@mE~y$aH*(yoM~5SEs8q~68Bli=dmk?jDxXiwH3
zJyNewJ8`}?K*Ep80^;$Tc{Ah541a(B2`Hqb
zCFD6=x)nq(%dk3epKx%rdTq|u>AFgzUXfPM
zIZ+uC7_G(?y9vKNQn2*Zt$0@|ZE=NURifHkCyB+C2JVJ}_wop8c?S{fiAJ1>gPs+3
z2fvI%3B&NNH$ftek@-BL8f$OR{opX>keVumGZ-B95f+F4!Za%qwzn9R)sp4V(+*oWuC}kq6yU>+3lcw<}WyfJCtxK{r
z_N@jSbyV(c?(E>F-FLU{80ot96>Cl3&93V%l-0cDManp@`Pb1+3oZN4+ora@LwSAI
z#}-vMz7U)MagqSPG&7P3X9gu)?hbJ;m*Wik2!~e_L>mQpdpUk<;B1CtHMQdqY4!m)
z*#4+6%~UP5wN}T5g%n`Ns{FVn)nnmEkTZem!L{yl7)69mrOI*jWdBaUGqP2@bYCx(
z?Fq=l@$g+k3S6kl&(KXbLfzv7BhsgQY9=;(gC^|fsyON9{FYYRni>_*rwNtbSedWX
RwAgE&{R6yf)WanU007NuYeE13
literal 683
zcmV;c0#yAUiwFP!000003bj^iZlf>|zDlHOrACSoAx)baY42k2K)f+FvQ3gU>dE%U
z9%-+zwt)a85AtJWCBfrw=9?Ge{QdnWppcP@8zdx!(}7X5#mg`(kMR~*zBPE`o)f7k
zD5MBwmA2$aA=GD~RTc(4V+ZI5=9qv}ddFSv0pE{AYqvYG#-eSOF)7?IEU2mz;dy
zUW}cr&?w_@?91GKkPyOIE^rFMfQnmGf?O=uxFvP1sNIW3x8GGu~E#^u?_>t(3O7QZk>YbJa;=ag~9aq2R6DgIe4`1Y4pJXJV%(h26nV
z<50pdyy;DlNMmF%ji|=j3c4R0#vC%^Q#gUaVIN^}_-{;;B2ljHj}Uo&KDQ5jiI
zqp-k}{Y=i4#ZFID1MU;t_xpkTwCILlQf8)m?_F=4b_92G^ML2I+pWVr>kUYdJdgW0F5LN-bG{VH5rY)L3(BCn^=g)x(5@fT(LVJK&pWM%AI
z4LItk+}qsQ!B6R{TQ`h!Q~QFocJAhvb!Wa00|h0{qn8kxV!V1EF1|6CQyBGt@<2B5ur1w3hbZk-wAj|wu=|;Ywm5|
Rf!sO%`Ul{II$Grk008_RO;G><
diff --git a/src/Blazor.Diagrams/wwwroot/style.min.css.gz b/src/Blazor.Diagrams/wwwroot/style.min.css.gz
index e72cb7d8af23d7af571c773a260d0f0ccfe835f3..4a312feec6aef85e5620eea68d1cd461ca9d351d 100644
GIT binary patch
delta 381
zcmV-@0fPRS1DOMmC4Wh48BgYeNAe1;l%j3Z86SNj{7L?N|FY!s{UbN1Td#Z7Xcu)D
zcWAgPABy6>>Hyo0kK-)`WF%L5u$nPKMFU%OPt*62Y%6?aB^~0arDH59CX=gL;Fk
z6C6J%gNzw0SU2HR=mQhi8IB*h!$TIvxoU~RwS{bX3>OT_UX
z1D}fT$UuVg#54qf4Pc?+8MdcGN)6ZIl`!{6FF2Ql(AHi+<(8Tam~q}Tum813`g1d0
z*v$E!^|xxOn|6Dhj@W7@KOPi11AD1cYC6ls!i%+v2)jg`YVrnr`MBL@qM*s{isH9Z
z>uK2jyZTO4lC48)Bwd29$0&$UI4J=p}{
bTMm0@2G-(}Sbi1$vK77n8oH^c9R&aY=R@iQw0k#`U0GyBrTUPbNQyVgwbUbGz}oKP{bX3>OT_6P
z1D}fT$UuVg#54qf4Pc?+8Mddllp3zZD`D=DUT`i8p{>1u$}Ke;Fw?wgUjJ*6^yg-}
zu$l8c>%D5Kn|6Dhj@W7@KfNh*26j@X)O41Mg%@iT5ynKFYVrnr`MBL>qM*s{isH9Z
z>uK2jyZW|!D#_NNHIgpDchxbe#y$TQnKYyHoO`NYgy?Kaeuo();
+ var control = new ResizeControl(resizeProvider.Object);
+ var model = new Mock();
+
+ control.GetPosition(model.Object);
+
+ resizeProvider.Verify(m => m.GetPosition(model.Object), Times.Once);
+ }
+
+ [Fact]
+ public void OnPointerDown_ShouldInvokeResizeStart()
+ {
+ var resizeProvider = new Mock();
+ var control = new ResizeControl(resizeProvider.Object);
+ var diagram = Mock.Of();
+ var model = Mock.Of();
+ var eventArgs = new PointerEventArgs(0, 0, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true);
+
+ control.OnPointerDown(diagram, model, eventArgs);
+
+ resizeProvider.Verify(m => m.OnResizeStart(diagram, model, eventArgs), Times.Once);
+ }
+
+ [Fact]
+ public void OnPointerDown_ShouldAddEventHandlers()
+ {
+ var resizeProvider = new Mock();
+ var control = new ResizeControl(resizeProvider.Object);
+ var diagram = new TestDiagram();
+ var model = Mock.Of();
+ var eventArgs = new PointerEventArgs(0, 0, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true);
+
+ control.OnPointerDown(diagram, model, eventArgs);
+
+ diagram.TriggerPointerMove(model, eventArgs);
+ resizeProvider.Verify(m => m.OnPointerMove(model, eventArgs), Times.Once);
+
+ diagram.TriggerPointerUp(model, eventArgs);
+ resizeProvider.Verify(m => m.OnResizeEnd(model, eventArgs), Times.Once);
+ }
+
+ [Fact]
+ public void OnPointerUp_ShouldRemoveEventHandlers()
+ {
+ var resizeProvider = new Mock();
+ var control = new ResizeControl(resizeProvider.Object);
+ var diagram = new TestDiagram();
+ var model = Mock.Of();
+ var eventArgs = new PointerEventArgs(0, 0, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true);
+
+ control.OnPointerDown(diagram, model, eventArgs);
+ diagram.TriggerPointerUp(model, eventArgs);
+
+ diagram.TriggerPointerMove(model, eventArgs);
+ resizeProvider.Verify(m => m.OnPointerMove(model, eventArgs), Times.Never);
+
+ diagram.TriggerPointerUp(model, eventArgs);
+ resizeProvider.Verify(m => m.OnResizeEnd(model, eventArgs), Times.Once);
+ }
+ }
+}
diff --git a/tests/Blazor.Diagrams.Core.Tests/Positions/Resizing/BottomLeftResizerProviderTests.cs b/tests/Blazor.Diagrams.Core.Tests/Positions/Resizing/BottomLeftResizerProviderTests.cs
new file mode 100644
index 000000000..79ef6c17b
--- /dev/null
+++ b/tests/Blazor.Diagrams.Core.Tests/Positions/Resizing/BottomLeftResizerProviderTests.cs
@@ -0,0 +1,82 @@
+using Blazor.Diagrams.Core.Controls.Default;
+using Blazor.Diagrams.Core.Events;
+using Blazor.Diagrams.Core.Geometry;
+using Blazor.Diagrams.Core.Models;
+using Blazor.Diagrams.Core.Positions.Resizing;
+using FluentAssertions;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace Blazor.Diagrams.Core.Tests.Positions.Resizing
+{
+ public class BottomLeftResizerProviderTests
+ {
+ [Fact]
+ public void DragResizer_ShouldResizeNode()
+ {
+ // setup
+ var diagram = new TestDiagram();
+ diagram.SetContainer(new Rectangle(0, 0, 1000, 400));
+ var node = new NodeModel(position: new Point(0, 0));
+ node.Size = new Size(100, 200);
+ var control = new ResizeControl(new BottomLeftResizerProvider());
+ diagram.Controls.AddFor(node).Add(control);
+ diagram.SelectModel(node, false);
+
+ // before resize
+ node.Position.X.Should().Be(0);
+ node.Position.Y.Should().Be(0);
+ node.Size.Width.Should().Be(100);
+ node.Size.Height.Should().Be(200);
+
+ // resize
+ var eventArgs = new PointerEventArgs(0, 0, 0, 0, false, false, false, 1, 1, 1, 1, 1, 1, "arrow", true);
+ control.OnPointerDown(diagram, node, eventArgs);
+ eventArgs = new PointerEventArgs(10, 15, 0, 0, false, false, false, 1, 1, 1, 1, 1, 1, "arrow", true);
+ diagram.TriggerPointerMove(null, eventArgs);
+
+ // after resize
+ node.Position.X.Should().Be(10);
+ node.Position.Y.Should().Be(0);
+ node.Size.Width.Should().Be(90);
+ node.Size.Height.Should().Be(215);
+ }
+
+ [Fact]
+ public void DragResizer_SmallerThanMinSize_SetsNodeToMinSize()
+ {
+ // setup
+ var diagram = new TestDiagram();
+ diagram.SetContainer(new Rectangle(0, 0, 1000, 400));
+ var node = new NodeModel(position: new Point(0, 0));
+ node.Size = new Size(100, 200);
+ var control = new ResizeControl(new BottomLeftResizerProvider());
+ diagram.Controls.AddFor(node).Add(control);
+ diagram.SelectModel(node, false);
+
+ // before resize
+ node.Position.X.Should().Be(0);
+ node.Position.Y.Should().Be(0);
+ node.Size.Width.Should().Be(100);
+ node.Size.Height.Should().Be(200);
+
+ // resize
+ var eventArgs = new PointerEventArgs(0, 0, 0, 0, false, false, false, 1, 1, 1, 1, 1, 1, "arrow", true);
+ control.OnPointerDown(diagram, node, eventArgs);
+ eventArgs = new PointerEventArgs(99, -199, 0, 0, false, false, false, 1, 1, 1, 1, 1, 1, "arrow", true);
+ diagram.TriggerPointerMove(null, eventArgs);
+ eventArgs = new PointerEventArgs(300, -300, 0, 0, false, false, false, 1, 1, 1, 1, 1, 1, "arrow", true);
+ diagram.TriggerPointerMove(null, eventArgs);
+
+ // after resize
+ node.Position.X.Should().Be(99);
+ node.Position.Y.Should().Be(0);
+ node.Size.Width.Should().Be(0);
+ node.Size.Height.Should().Be(0);
+ }
+ }
+}
diff --git a/tests/Blazor.Diagrams.Core.Tests/Positions/Resizing/BottomRightResizerProviderTests.cs b/tests/Blazor.Diagrams.Core.Tests/Positions/Resizing/BottomRightResizerProviderTests.cs
new file mode 100644
index 000000000..20ab27770
--- /dev/null
+++ b/tests/Blazor.Diagrams.Core.Tests/Positions/Resizing/BottomRightResizerProviderTests.cs
@@ -0,0 +1,80 @@
+using Blazor.Diagrams.Core.Controls.Default;
+using Blazor.Diagrams.Core.Events;
+using Blazor.Diagrams.Core.Geometry;
+using Blazor.Diagrams.Core.Models;
+using Blazor.Diagrams.Core.Positions.Resizing;
+using FluentAssertions;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace Blazor.Diagrams.Core.Tests.Positions.Resizing
+{
+ public class BottomRightResizerProviderTests
+ {
+ [Fact]
+ public void DragResizer_ShouldResizeNode()
+ {
+ // setup
+ var diagram = new TestDiagram();
+ diagram.SetContainer(new Rectangle(0, 0, 1000, 400));
+ var node = new NodeModel(position: new Point(0, 0));
+ node.Size = new Size(100, 200);
+ var control = new ResizeControl(new BottomRightResizerProvider());
+ diagram.Controls.AddFor(node).Add(control);
+ diagram.SelectModel(node, false);
+
+ // before resize
+ node.Position.X.Should().Be(0);
+ node.Position.Y.Should().Be(0);
+ node.Size.Width.Should().Be(100);
+ node.Size.Height.Should().Be(200);
+
+ // resize
+ var eventArgs = new PointerEventArgs(0, 0, 0, 0, false, false, false, 1, 1, 1, 1, 1, 1, "arrow", true);
+ control.OnPointerDown(diagram, node, eventArgs);
+ eventArgs = new PointerEventArgs(10, 15, 0, 0, false, false, false, 1, 1, 1, 1, 1, 1, "arrow", true);
+ diagram.TriggerPointerMove(null, eventArgs);
+
+ // after resize
+ node.Position.X.Should().Be(0);
+ node.Position.Y.Should().Be(0);
+ node.Size.Width.Should().Be(110);
+ node.Size.Height.Should().Be(215);
+ }
+
+ [Fact]
+ public void DragResizer_SmallerThanMinSize_SetsNodeToMinSize()
+ {
+ // setup
+ var diagram = new TestDiagram();
+ diagram.SetContainer(new Rectangle(0, 0, 1000, 400));
+ var node = new NodeModel(position: new Point(0, 0));
+ node.Size = new Size(100, 200);
+ var control = new ResizeControl(new BottomRightResizerProvider());
+ diagram.Controls.AddFor(node).Add(control);
+ diagram.SelectModel(node, false);
+
+ // before resize
+ node.Position.X.Should().Be(0);
+ node.Position.Y.Should().Be(0);
+ node.Size.Width.Should().Be(100);
+ node.Size.Height.Should().Be(200);
+
+ // resize
+ var eventArgs = new PointerEventArgs(0, 0, 0, 0, false, false, false, 1, 1, 1, 1, 1, 1, "arrow", true);
+ control.OnPointerDown(diagram, node, eventArgs);
+ eventArgs = new PointerEventArgs(-300, -300, 0, 0, false, false, false, 1, 1, 1, 1, 1, 1, "arrow", true);
+ diagram.TriggerPointerMove(null, eventArgs);
+
+ // after resize
+ node.Position.X.Should().Be(0);
+ node.Position.Y.Should().Be(0);
+ node.Size.Width.Should().Be(0);
+ node.Size.Height.Should().Be(0);
+ }
+ }
+}
diff --git a/tests/Blazor.Diagrams.Core.Tests/Positions/Resizing/TopLeftResizerProviderTests.cs b/tests/Blazor.Diagrams.Core.Tests/Positions/Resizing/TopLeftResizerProviderTests.cs
new file mode 100644
index 000000000..1cc715d59
--- /dev/null
+++ b/tests/Blazor.Diagrams.Core.Tests/Positions/Resizing/TopLeftResizerProviderTests.cs
@@ -0,0 +1,82 @@
+using Blazor.Diagrams.Core.Controls.Default;
+using Blazor.Diagrams.Core.Events;
+using Blazor.Diagrams.Core.Geometry;
+using Blazor.Diagrams.Core.Models;
+using Blazor.Diagrams.Core.Positions.Resizing;
+using FluentAssertions;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace Blazor.Diagrams.Core.Tests.Positions.Resizing
+{
+ public class TopLeftResizerProviderTests
+ {
+ [Fact]
+ public void DragResizer_ShouldResizeNode()
+ {
+ // setup
+ var diagram = new TestDiagram();
+ diagram.SetContainer(new Rectangle(0, 0, 1000, 400));
+ var node = new NodeModel(position: new Point(0, 0));
+ node.Size = new Size(100, 200);
+ var control = new ResizeControl(new TopLeftResizerProvider());
+ diagram.Controls.AddFor(node).Add(control);
+ diagram.SelectModel(node, false);
+
+ // before resize
+ node.Position.X.Should().Be(0);
+ node.Position.Y.Should().Be(0);
+ node.Size.Width.Should().Be(100);
+ node.Size.Height.Should().Be(200);
+
+ // resize
+ var eventArgs = new PointerEventArgs(0, 0, 0, 0, false, false, false, 1, 1, 1, 1, 1, 1, "arrow", true);
+ control.OnPointerDown(diagram, node, eventArgs);
+ eventArgs = new PointerEventArgs(10, 15, 0, 0, false, false, false, 1, 1, 1, 1, 1, 1, "arrow", true);
+ diagram.TriggerPointerMove(null, eventArgs);
+
+ // after resize
+ node.Position.X.Should().Be(10);
+ node.Position.Y.Should().Be(15);
+ node.Size.Width.Should().Be(90);
+ node.Size.Height.Should().Be(185);
+ }
+
+ [Fact]
+ public void DragResizer_SmallerThanMinSize_SetsNodeToMinSize()
+ {
+ // setup
+ var diagram = new TestDiagram();
+ diagram.SetContainer(new Rectangle(0, 0, 1000, 400));
+ var node = new NodeModel(position: new Point(0, 0));
+ node.Size = new Size(100, 200);
+ var control = new ResizeControl(new TopLeftResizerProvider());
+ diagram.Controls.AddFor(node).Add(control);
+ diagram.SelectModel(node, false);
+
+ // before resize
+ node.Position.X.Should().Be(0);
+ node.Position.Y.Should().Be(0);
+ node.Size.Width.Should().Be(100);
+ node.Size.Height.Should().Be(200);
+
+ // resize
+ var eventArgs = new PointerEventArgs(0, 0, 0, 0, false, false, false, 1, 1, 1, 1, 1, 1, "arrow", true);
+ control.OnPointerDown(diagram, node, eventArgs);
+ eventArgs = new PointerEventArgs(99, 199, 0, 0, false, false, false, 1, 1, 1, 1, 1, 1, "arrow", true);
+ diagram.TriggerPointerMove(null, eventArgs);
+ eventArgs = new PointerEventArgs(300, 300, 0, 0, false, false, false, 1, 1, 1, 1, 1, 1, "arrow", true);
+ diagram.TriggerPointerMove(null, eventArgs);
+
+ // after resize
+ node.Position.X.Should().Be(99);
+ node.Position.Y.Should().Be(199);
+ node.Size.Width.Should().Be(0);
+ node.Size.Height.Should().Be(0);
+ }
+ }
+}
diff --git a/tests/Blazor.Diagrams.Core.Tests/Positions/Resizing/TopRightResizerProviderTests.cs b/tests/Blazor.Diagrams.Core.Tests/Positions/Resizing/TopRightResizerProviderTests.cs
new file mode 100644
index 000000000..a138d524f
--- /dev/null
+++ b/tests/Blazor.Diagrams.Core.Tests/Positions/Resizing/TopRightResizerProviderTests.cs
@@ -0,0 +1,82 @@
+using Blazor.Diagrams.Core.Controls.Default;
+using Blazor.Diagrams.Core.Events;
+using Blazor.Diagrams.Core.Geometry;
+using Blazor.Diagrams.Core.Models;
+using Blazor.Diagrams.Core.Positions.Resizing;
+using FluentAssertions;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace Blazor.Diagrams.Core.Tests.Positions.Resizing
+{
+ public class TopRightResizerProviderTests
+ {
+ [Fact]
+ public void DragResizer_ShouldResizeNode()
+ {
+ // setup
+ var diagram = new TestDiagram();
+ diagram.SetContainer(new Rectangle(0, 0, 1000, 400));
+ var node = new NodeModel(position: new Point(0, 0));
+ node.Size = new Size(100, 200);
+ var control = new ResizeControl(new TopRightResizerProvider());
+ diagram.Controls.AddFor(node).Add(control);
+ diagram.SelectModel(node, false);
+
+ // before resize
+ node.Position.X.Should().Be(0);
+ node.Position.Y.Should().Be(0);
+ node.Size.Width.Should().Be(100);
+ node.Size.Height.Should().Be(200);
+
+ // resize
+ var eventArgs = new PointerEventArgs(0, 0, 0, 0, false, false, false, 1, 1, 1, 1, 1, 1, "arrow", true);
+ control.OnPointerDown(diagram, node, eventArgs);
+ eventArgs = new PointerEventArgs(10, 15, 0, 0, false, false, false, 1, 1, 1, 1, 1, 1, "arrow", true);
+ diagram.TriggerPointerMove(null, eventArgs);
+
+ // after resize
+ node.Position.X.Should().Be(0);
+ node.Position.Y.Should().Be(15);
+ node.Size.Width.Should().Be(110);
+ node.Size.Height.Should().Be(185);
+ }
+
+ [Fact]
+ public void DragResizer_SmallerThanMinSize_SetsNodeToMinSize()
+ {
+ // setup
+ var diagram = new TestDiagram();
+ diagram.SetContainer(new Rectangle(0, 0, 1000, 400));
+ var node = new NodeModel(position: new Point(0, 0));
+ node.Size = new Size(100, 200);
+ var control = new ResizeControl(new TopRightResizerProvider());
+ diagram.Controls.AddFor(node).Add(control);
+ diagram.SelectModel(node, false);
+
+ // before resize
+ node.Position.X.Should().Be(0);
+ node.Position.Y.Should().Be(0);
+ node.Size.Width.Should().Be(100);
+ node.Size.Height.Should().Be(200);
+
+ // resize
+ var eventArgs = new PointerEventArgs(0, 0, 0, 0, false, false, false, 1, 1, 1, 1, 1, 1, "arrow", true);
+ control.OnPointerDown(diagram, node, eventArgs);
+ eventArgs = new PointerEventArgs(-99, 199, 0, 0, false, false, false, 1, 1, 1, 1, 1, 1, "arrow", true);
+ diagram.TriggerPointerMove(null, eventArgs);
+ eventArgs = new PointerEventArgs(-300, 300, 0, 0, false, false, false, 1, 1, 1, 1, 1, 1, "arrow", true);
+ diagram.TriggerPointerMove(null, eventArgs);
+
+ // after resize
+ node.Position.X.Should().Be(0);
+ node.Position.Y.Should().Be(199);
+ node.Size.Width.Should().Be(0);
+ node.Size.Height.Should().Be(0);
+ }
+ }
+}
diff --git a/tests/Blazor.Diagrams.Tests/Components/Controls/ResizeControlWidgetTests.cs b/tests/Blazor.Diagrams.Tests/Components/Controls/ResizeControlWidgetTests.cs
new file mode 100644
index 000000000..bf51e541c
--- /dev/null
+++ b/tests/Blazor.Diagrams.Tests/Components/Controls/ResizeControlWidgetTests.cs
@@ -0,0 +1,25 @@
+using Blazor.Diagrams.Components.Controls;
+using Blazor.Diagrams.Core.Controls.Default;
+using Blazor.Diagrams.Core.Positions.Resizing;
+using Bunit;
+using Moq;
+using Xunit;
+
+namespace Blazor.Diagrams.Tests.Components.Controls
+{
+ public class ResizeControlWidgetTests
+ {
+ [Fact]
+ public void ShouldRenderDiv()
+ {
+ using var ctx = new TestContext();
+ var providerMock = Mock.Of();
+
+ var cut = ctx.RenderComponent(parameters =>
+ parameters.Add(w => w.Control, new ResizeControl(providerMock))
+ );
+
+ cut.MarkupMatches("");
+ }
+ }
+}