Skip to content

Commit

Permalink
Merge pull request #135 from Blazor-Diagrams/develop
Browse files Browse the repository at this point in the history
Version 2.1.4
  • Loading branch information
zHaytam authored Aug 29, 2021
2 parents 664c337 + aa1e963 commit 9ed7e1d
Show file tree
Hide file tree
Showing 14 changed files with 354 additions and 11 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Binary file added ZBD_Title.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions samples/SharedDemo/Demos/Events.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
15 changes: 15 additions & 0 deletions src/Blazor.Diagrams.Core/Behaviors/EventsBehavior.cs
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
6 changes: 3 additions & 3 deletions src/Blazor.Diagrams.Core/Blazor.Diagrams.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<Authors>zHaytam</Authors>
<Description>A fully customizable and extensible all-purpose diagrams library for Blazor</Description>
<AssemblyVersion>2.1.3</AssemblyVersion>
<FileVersion>2.1.3</FileVersion>
<AssemblyVersion>2.1.4</AssemblyVersion>
<FileVersion>2.1.4</FileVersion>
<RepositoryUrl>https://github.com/zHaytam/Blazor.Diagrams</RepositoryUrl>
<Version>2.1.3</Version>
<Version>2.1.4</Version>
<PackageId>Z.Blazor.Diagrams.Core</PackageId>
<PackageTags>blazor diagrams diagramming svg drag</PackageTags>
<Product>Z.Blazor.Diagrams.Core</Product>
Expand Down
21 changes: 20 additions & 1 deletion src/Blazor.Diagrams.Core/Diagram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public class Diagram : Model
public event Action<KeyboardEventArgs>? KeyDown;
public event Action<WheelEventArgs>? Wheel;
public event Action<Model, MouseEventArgs>? MouseClick;
public event Action<Model, MouseEventArgs>? MouseDoubleClick;
public event Action<Model, TouchEventArgs>? TouchStart;
public event Action<Model, TouchEventArgs>? TouchMove;
public event Action<Model, TouchEventArgs>? TouchEnd;
Expand Down Expand Up @@ -294,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)
Expand Down Expand Up @@ -341,6 +346,16 @@ 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);

internal void OnMouseMove(Model model, MouseEventArgs e) => MouseMove?.Invoke(model, e);
Expand All @@ -353,10 +368,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
}
}
6 changes: 4 additions & 2 deletions src/Blazor.Diagrams.Core/Models/Base/BaseLinkModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
}

Expand All @@ -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);
}
}
Expand Down
1 change: 1 addition & 0 deletions src/Blazor.Diagrams.Core/Models/NodeModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public Size? Size
}
}
public GroupModel? Group { get; internal set; }
public string Title { get; set; }

public IReadOnlyList<PortModel> Ports => _ports;
public IReadOnlyList<BaseLinkModel> Links => _links;
Expand Down
6 changes: 3 additions & 3 deletions src/Blazor.Diagrams/Blazor.Diagrams.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
<RazorLangVersion>3.0</RazorLangVersion>
<Authors>zHaytam</Authors>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<AssemblyVersion>2.1.3</AssemblyVersion>
<FileVersion>2.1.3</FileVersion>
<AssemblyVersion>2.1.4</AssemblyVersion>
<FileVersion>2.1.4</FileVersion>
<RepositoryUrl>https://github.com/zHaytam/Blazor.Diagrams</RepositoryUrl>
<Description>A fully customizable and extensible all-purpose diagrams library for Blazor</Description>
<Version>2.1.3</Version>
<Version>2.1.4</Version>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageTags>blazor diagrams diagramming svg drag</PackageTags>
<PackageId>Z.Blazor.Diagrams</PackageId>
Expand Down
2 changes: 1 addition & 1 deletion src/Blazor.Diagrams/Components/NodeWidget.razor
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div class="default-node @(Node.Group != null ? "grouped" : "") @(Node.Selected ? "selected" : "")">
Node Title
@(Node.Title ?? "Title")
@foreach (var port in Node.Ports)
{
<PortRenderer Port="port" Class="default"></PortRenderer>
Expand Down
94 changes: 94 additions & 0 deletions tests/Blazor.Diagrams.Core.Tests/Behaviors/EventsBehaviorTests.cs
Original file line number Diff line number Diff line change
@@ -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<EventsBehavior>();
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();
}
}
}
95 changes: 95 additions & 0 deletions tests/Blazor.Diagrams.Core.Tests/DiagramTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
using Blazor.Diagrams.Core.Geometry;
using Blazor.Diagrams.Core.Models;
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
}

[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);
}
}
}
Loading

0 comments on commit 9ed7e1d

Please sign in to comment.