diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 23fd31588..98fc1e5c0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -36,7 +36,7 @@ jobs: - name: Pack if: matrix.configuration == 'Release' - run: dotnet pack --configuration ${{ matrix.configuration }} -o packages + run: dotnet pack --configuration ${{ matrix.configuration }} -o packages --no-build - name: Upload packages if: matrix.configuration == 'Release' diff --git a/Blazor.Diagrams.sln b/Blazor.Diagrams.sln index 7f2699817..5f73d1027 100644 --- a/Blazor.Diagrams.sln +++ b/Blazor.Diagrams.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30114.128 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.32014.148 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{EE32E278-A887-454E-987D-FFE9E37169FE}" EndProject @@ -21,7 +21,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blazor.Diagrams.Algorithms" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{260DF53D-FF2B-4D1D-ACA7-431F6B62EE38}" ProjectSection(SolutionItems) = preProject + .github\workflows\build.yml = .github\workflows\build.yml CHANGELOG.md = CHANGELOG.md + .github\workflows\main.yml = .github\workflows\main.yml README.md = README.md EndProjectSection EndProject @@ -31,11 +33,17 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blazor.Diagrams.Core.Tests" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{A9FC9B20-A9F1-4066-8B59-83BD26D3B1C8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Diagram-Demo", "docs\Diagram-Demo\Diagram-Demo.csproj", "{5F423724-5319-4DCE-B9F2-8B2D7E1FDC17}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Diagram-Demo", "docs\Diagram-Demo\Diagram-Demo.csproj", "{5F423724-5319-4DCE-B9F2-8B2D7E1FDC17}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomNodesLinks", "docs\CustomNodesLinks\CustomNodesLinks.csproj", "{3D104DB4-C7F0-42CA-9D78-AB2C8A8AE3D5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CustomNodesLinks", "docs\CustomNodesLinks\CustomNodesLinks.csproj", "{3D104DB4-C7F0-42CA-9D78-AB2C8A8AE3D5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Layouts", "docs\Layouts\Layouts.csproj", "{78C85C89-B464-4083-8829-78BA52BB4780}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Layouts", "docs\Layouts\Layouts.csproj", "{78C85C89-B464-4083-8829-78BA52BB4780}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blazor.Diagrams.Tests", "tests\Blazor.Diagrams.Tests\Blazor.Diagrams.Tests.csproj", "{ED3B0D8F-F29A-4C66-A167-C36824A76902}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "site", "site", "{F1E6F4C0-3EC7-4CFF-834A-0CF207CCFF3E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Site", "site\Site\Site.csproj", "{F26307EC-C188-44BD-B3E5-960318F43C0C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -83,6 +91,14 @@ Global {78C85C89-B464-4083-8829-78BA52BB4780}.Debug|Any CPU.Build.0 = Debug|Any CPU {78C85C89-B464-4083-8829-78BA52BB4780}.Release|Any CPU.ActiveCfg = Release|Any CPU {78C85C89-B464-4083-8829-78BA52BB4780}.Release|Any CPU.Build.0 = Release|Any CPU + {ED3B0D8F-F29A-4C66-A167-C36824A76902}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ED3B0D8F-F29A-4C66-A167-C36824A76902}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ED3B0D8F-F29A-4C66-A167-C36824A76902}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ED3B0D8F-F29A-4C66-A167-C36824A76902}.Release|Any CPU.Build.0 = Release|Any CPU + {F26307EC-C188-44BD-B3E5-960318F43C0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F26307EC-C188-44BD-B3E5-960318F43C0C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F26307EC-C188-44BD-B3E5-960318F43C0C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F26307EC-C188-44BD-B3E5-960318F43C0C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -98,6 +114,8 @@ Global {5F423724-5319-4DCE-B9F2-8B2D7E1FDC17} = {A9FC9B20-A9F1-4066-8B59-83BD26D3B1C8} {3D104DB4-C7F0-42CA-9D78-AB2C8A8AE3D5} = {A9FC9B20-A9F1-4066-8B59-83BD26D3B1C8} {78C85C89-B464-4083-8829-78BA52BB4780} = {A9FC9B20-A9F1-4066-8B59-83BD26D3B1C8} + {ED3B0D8F-F29A-4C66-A167-C36824A76902} = {CEEAE4C2-CE68-4FC3-9E0F-D4781B91F7F4} + {F26307EC-C188-44BD-B3E5-960318F43C0C} = {F1E6F4C0-3EC7-4CFF-834A-0CF207CCFF3E} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {969540A2-8162-4063-A4E3-B488F69BD582} diff --git a/CHANGELOG.md b/CHANGELOG.md index efcbd7449..e5358a9a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,252 @@ + # Changelog 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 (3.0.0) - 2023-08-14 + +Finally, the new documentation website is here! +Please don't hesitate to create issues for any problems or improvements. +PS: I suck at design. + +### Added + +- `AddLabel` method to links to easily create `LinkLabelModel` +- `AddVertex` method to links to easily create `LinkVertexModel` +- `ControlledSize` property to nodes. If `true`, the node will not be registered in the `ResizeObserver` (saves a JS call). +- `autoSize` argument to `SvgGroupModel` constructor + +### Changed + +- Renamed `Point.Substract` to `Subtract` (duh) +- Avoid rendering link selection helper on dragged link + +### Fixed + +- `SmoothPathGenerator` not working with `LinkAnchor` +- Mouse overlapping dragged link +- Useless Console Logs from `GroupModel` are now removed +- JS exception in `(un)oberve` methods when the element doesn't exist anymore + +## Diagrams (3.0.0-beta.6) - 2023-05-09 + +### Added + +- `Style` parameter to `PortRenderer` +- `TargetAttached` to links, which triggers when a dragged link attaches to a target + - If port snapping is enabled, it will trigger only once when you let go of the mouse +- `SuspendSorting` to `Diagram` in order to suspend sorting models in each `OrderChanged` + - If you know what you're doing, you could save some processing and avoid sorting everytime +- `RefreshOrders` to be called after unsuspending sorting in order to sort the models again and refresh the diagram + +### Changed + +- `BaseLayer.Add` now returns the specific type given to it in argument +- **[BREAKING]** CSS classes are now prefixed with `diagram-` to avoid clashes with other libraries + - `diagram-group`, `diagram-node`, `diagram-link`, `diagram-port`, `diagram-link-label`, `diagram-link-vertex`, `diagram-control` + +### Fixed + +- Portless links in children not refreshing when moving the parent group +- Link's `GetBounds` not returning a valid box +- Port snapping choosing the first port in radius rather than the closest one +- Remove `Console.WriteLine` from `KeyboardShortcutsBehavior` +- Diagram overwriting `Order` when it's not zero (zero being the default int value, which we now consider as not set) + +## Diagrams (3.0.0-beta.5) - 2022-11-23 + +### Added + +- `AdditionalSvg` option to `DiagramCanvas` in order to render any exatra SVG content you want +- `AdditionalHtml` option to `DiagramCanvas` in order to render any exatra SVG content you want +- `DistanceTo` overload method to `Point` that takes x and y +- `MoveAlongLine` method to `Point` +- `FullPath` to `PathGeneratorResult` to represent the full path without cuts +- Fallback router to Orthogonal router +- Margin options to `OrthogonalRouter` +- `radius` option to `StraightPathGenerator` in order to generate rounded bends +- Support for custom vertices +- `AutoSize` option to groups to control whether moving children resizes the group + +### Changed + +- All routers are now classes instead of functions, they inherit from the new abstract class `Router` +- All path generators are now classes instead of functions, they inherit from the new abstract class `PathGenerator` +- Optimize Orthogonal router by using custom A* (x5 improvement) + +### Removed + +- `Router` delegate +- `PathGenerator` delegate + +## Diagrams (3.0.0-beta.4) - 2022-10-16 + +### Added + +- Initial version of Ordering! + - Nodes, groups and links can now be ordered using the new `Order` property or `SendToFront/Back` methods + - `Diagram.OrderedSelectables` returns the ordered selectables/models + - `DiagramCanvas` now uses this new property to render everything +- `GridSnapToCenter` option in order to snap nodes from their center instead of their top/left position (thanks to @[Jeremy Vance](https://github.com/240026763)) +- More unit tests + +### Changed + +- `Groups` is not a list of groups anymore, but a layer instead (just like `Nodes` and `Links`) + +### Fixed + +- Deleting a group doesn't delete links attached to it +- Deleting a group inside of a group doesn't refresh the parent group +- Links not refreshing when a group's dimensions are updated directly (e.g. deleting a child) +- Layers causing more refreshes than intended + +### Removed + +- All group-related methods and events from `Diagram`, please use the new layer from now on + +## Diagrams (3.0.0-beta.3) - 2022-09-18 + +### Added + +- Support for `LinkFactory` to return null in order to not create an ongoing link +- Support for free links (no source/target required) +- `PositionAnchor` which reprensents a simple plain position (mutable) +- `ArrowHeadControl` to control a link's Source/Target on the fly +- `attached` css class to attached links + +### Changed + +- Replace `OngoingPosition` with the new `PositionAnchor` + - `BaseLinkModel.Target` will never be null anymore. An ongoing link will have a position anchor as the target +- `Links.Factory` signature now takes the diagram, source (model) and the target anchor +- Move `DynamicAnchor` back to `Anchors` namespace and seal all `Anchor` classes + +### Fixed + +- Links attached to links not refreshing when the others are +- `LinkPathPositionProvider` not working with maxlength ratios +- Deleting a link not deleting the links attached to it + +### Removed + +- `PositionProvider` argument from `ExecutableControl` for more freedom +- `Id` and `Refresh` from `ILinkable` +- Unused `Offset` from `Anchor` and make `Model` nullable + +## Diagrams (3.0.0-beta.2) - 2022-09-11 + +### Added + +- `Moved` event to Movables +- `Visible` property and `VisbilityChanged` event to models +- `Options.Virtualization` (of type `[Diagram]VirtualizationOptions`) for virtualization options +- `PointerEnter/Leave` events for groups as well +- **Experimental Link to Link** (using `LinkAnchor`) + +### Changed + +- Rename `RegisterModelComponent` to `RegisterComponent` +- Rename `GetComponentForModel` to `GetComponent` +- Virtualization is now handled by a behavior instead of NodeRender + - This means that it works for almost all models (nodes, groups and links) +- Render link labels without foreignObject in widget nor MarkupString (Thank you .NET 6) +- Custom link labels only need to contain relevant content, they don't need to handle positioning anymore + +### Removed + +- `EnableVirtualization` option (see added alternative) + +## Diagrams (3.0.0-beta.1) - 2022-09-04 + +.NET 6! + +A lot of things changed in this version, a lot of breaking changes were introduced but I believe it was necessary. +Many changes were required to make everything clearer, customizable and cleaner (code wise). +I'm aiming to completely decouple the Core library from the UI, because I'm thinking of giving MAUI Diagrams a try very soon! + +### Added + +- `BlazorDiagram` class (inherits `Diagram`) to the blazor package to replace the old Core one +- `BlazorDiagramOptions` that inherit from the other diagram options to add Blazor (UI) specific options +- `Blazor.Diagrams.Models.SvgNodeModel` class to represent a node that needs to be rendered in the SVG layer +- `GetBehavior` method to `Diagram` in order to retrieve a registered behavior +- `KeyboardShortcutsBehavior` class which handles keyboard shortcuts/actions: + - `SetShortcut`: sets an action (`Func`) to be executed whenever the specified combination is pressed + - `RemoveShortcut`: removes a defined action (if it exists) +- `KeyboardShortcutsDefaults` containing the default shortcuts that were deleted (`DeleteSelection` and `Grouping`) +- Anchors functionality: + - An Anchor determines where on an element the link will connect + - Instead of links requiring the source and target to be either both nodes or both ports, there is now only one `Source` and `Target` of type `Anchor` + - This lets the link not worry about the details of from/to where its going, as long as the anchor provides it with its position when asked for + - Current implementations: + - `SinglePortAnchor`: Specifies that the connection point is a specific port (supports shape & alignment) + - `ShapeIntersectionAnchor`: Specifies that the connection point is the intersection of a line with the node's shape + - `DynamicAnchor`: Specifies that the connection point is one of the given positions (closest) +- Virtual `IShape GetShape()` method on nodes (default `Rectangle`) and ports (default `Circle`) +- `Options.LinksLayerOrder` to indicate the order of the links layer (svg for blazor) +- `Options.NodesLayerOrder` to indicate the order of the nodes layer (html for blazor) +- Support for SVG groups that also represent children as a hierarchy (`SvgGroupModel`) +- Node renderer will now append, in addition to `node locked`, the classes `selected grouped` +- `IHasBounds` and `IHasShape` interfaces to both nodes and ports +- `IPositionProvider` to encapsulate how certain positions are calculated given a model + - They are used for dynamic anchors and controls for now + - `BoundsBasedPositionProvider` returns the position based on the bounds of the model (e.g. (0.5, 0.5) would be the center) + - `ShapeAnglePositionProvider` returns the position as the point at the angle of the shape + - `LinkPathPositionProvider` returns the position based on the link's path (`getPointAtLength`) +- Links have a reference to `Diagram` now +- `PointerEnter` and `PointerLeave` events for nodes and links for now +- `GeneratedPathResult` and `Paths` to `BaseLinkModel` to always have access to the actual paths +- `Controls` feature (beta): + - They are things that can show up on top of nodes/links and can even be clicked to be executed + - Their UI is also picked up from the registered components + - `Control` designates a control that has a position and will be rendered if visible + - `ExecutableControl` designates a control that has a position and will be executed when pressed (PointerDown event) + - Default controls for now are: + - `BoundaryControl` shows the model's boundary + - `RemoveControl` shows a button that when clicked, removes the model from the diagram + - `DragNewLink` shows a button that when clicked, starts a new link dragging from that node +- `GridWidget` a background grid that moves with the diagram instead of being fixed like in the Snap to grid example +- More unit tests + +### Changed + +- Core package changes: + - Web dependency was removed from the Core package + - `Diagram` is now abstract + - These changes were done to decouple the core from the rendering, in the future we might have a MAUI renderer +- `Diagram.GetComponentForModel` now accepts a `checkSubclasses` argument (default `true`) +- Constraints now must return a `ValueTask` instead of a simple `bool` +- Renamed `AllLinks` to `PortLinks` for more clarity on which links, since `Links` contains the others +- Dragging links from ports will now follow the mouse at the same pace minus 5 pixels so that it doesn't go on top of the link it self or other ports +- How groups are rendered + - `GroupRenderer` will take care of rendering the group with the appropriate style and classes + - Only `GroupNodes` is required, `GroupLinks` was deleted because all links are shown in the svg layer (with appropriate order) +- `Diagram.AddGroup` will now return the added group +- All `Mouse` events have been converted to `Pointer` events +- `PathGenerator` now return `SvgPath` instead of just strings +- `NavigatorWidget` was rewritten to be faster, lighter, WORKING and customizable + - It now can also take the shape of the nodes into account (rect and ellipse for now) + +### Fixed + +- Virtualization throwing a JSException (#155) +- Ports not rendering correctly because of the missing `@key` (#220) +- Link not refreshing when a new vertex is created, which was showing out of link + +### Removed + +- `DefaultNodeComponent` and `DefaultLinkComponent` options (see `GetComponentForModel` changes) +- `RenderLayer` from the Core package and all its usage +- `DeleteSelectionBehavior` since there is a new keyboard shortcuts system +- `GroupingBehavior` since there is a new keyboard shortcuts system +- `BaseLinkModelExtensions` since it was Obselete +- Unnecessary port refreshes when dragging a link ends or when link snapping +- `ShapeDefiner` delegate and constructor arguments on nodes since delegates can't be serialized +- `TouchX` events + ## Diagrams (2.1.6) - 2021-10-31 ### Fixed diff --git a/docs/CustomNodesLinks/CustomNodesLinks.csproj b/docs/CustomNodesLinks/CustomNodesLinks.csproj index 2f00b3a27..0b40cdb67 100644 --- a/docs/CustomNodesLinks/CustomNodesLinks.csproj +++ b/docs/CustomNodesLinks/CustomNodesLinks.csproj @@ -1,7 +1,7 @@ - net5.0 + net6.0 diff --git a/docs/CustomNodesLinks/Models/DiagramLink.cs b/docs/CustomNodesLinks/Models/DiagramLink.cs index a64954402..325e96839 100644 --- a/docs/CustomNodesLinks/Models/DiagramLink.cs +++ b/docs/CustomNodesLinks/Models/DiagramLink.cs @@ -1,16 +1,15 @@ using Blazor.Diagrams.Core.Models; -namespace CustomNodesLinks.Models +namespace CustomNodesLinks.Models; + +public sealed class DiagramLink : LinkModel +{ +public DiagramLink(string name, NodeModel sourceNode, NodeModel? targetNode) : + base(name, sourceNode, targetNode) { - public sealed class DiagramLink : LinkModel - { - public DiagramLink(string name, NodeModel sourceNode, NodeModel? targetNode) : - base(name, sourceNode, targetNode) - { - Name = name; - Labels.Add(new DiagramLinkLabel(this, Name)); - } + Name = name; + Labels.Add(new DiagramLinkLabel(this, Name)); +} - public string Name { get; set; } - } +public string Name { get; set; } } diff --git a/docs/CustomNodesLinks/Models/DiagramLinkLabel.cs b/docs/CustomNodesLinks/Models/DiagramLinkLabel.cs index 2b799cee7..99a0cbbaa 100644 --- a/docs/CustomNodesLinks/Models/DiagramLinkLabel.cs +++ b/docs/CustomNodesLinks/Models/DiagramLinkLabel.cs @@ -2,20 +2,19 @@ using Blazor.Diagrams.Core.Models; using Blazor.Diagrams.Core.Models.Base; -namespace CustomNodesLinks.Models +namespace CustomNodesLinks.Models; + +public sealed class DiagramLinkLabel : LinkLabelModel +{ +public DiagramLinkLabel(BaseLinkModel parent, string id, string content, double? distance = null, Point? offset = null) : + base(parent, id, content, distance, offset) { - public sealed class DiagramLinkLabel : LinkLabelModel - { - public DiagramLinkLabel(BaseLinkModel parent, string id, string content, double? distance = null, Point? offset = null) : - base(parent, id, content, distance, offset) - { - } +} - public DiagramLinkLabel(BaseLinkModel parent, string content, double? distance = null, Point? offset = null) : - base(parent, content, distance, offset) - { - } +public DiagramLinkLabel(BaseLinkModel parent, string content, double? distance = null, Point? offset = null) : + base(parent, content, distance, offset) +{ +} - public bool ShowLabel { get; set; } = true; - } +public bool ShowLabel { get; set; } = true; } diff --git a/docs/CustomNodesLinks/Models/DiagramNode.cs b/docs/CustomNodesLinks/Models/DiagramNode.cs index 66e5e97b0..20eebd0c8 100644 --- a/docs/CustomNodesLinks/Models/DiagramNode.cs +++ b/docs/CustomNodesLinks/Models/DiagramNode.cs @@ -1,16 +1,15 @@ using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Core.Models; -namespace CustomNodesLinks.Models +namespace CustomNodesLinks.Models; + +public sealed class DiagramNode : NodeModel +{ +public DiagramNode(string name, Point pos) : + base(name, pos) { - public sealed class DiagramNode : NodeModel - { - public DiagramNode(string name, Point pos) : - base(name, pos) - { - Name = name; - } + Name = name; +} - public string Name { get; set; } - } +public string Name { get; set; } } diff --git a/docs/CustomNodesLinks/Pages/Error.cshtml.cs b/docs/CustomNodesLinks/Pages/Error.cshtml.cs index b83dc4a17..99ccc5af5 100644 --- a/docs/CustomNodesLinks/Pages/Error.cshtml.cs +++ b/docs/CustomNodesLinks/Pages/Error.cshtml.cs @@ -1,32 +1,27 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Threading.Tasks; +using System.Diagnostics; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Logging; -namespace CustomNodesLinks.Pages +namespace CustomNodesLinks.Pages; + +[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] +[IgnoreAntiforgeryToken] +public class ErrorModel : PageModel { - [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] - [IgnoreAntiforgeryToken] - public class ErrorModel : PageModel - { - public string RequestId { get; set; } +public string RequestId { get; set; } - public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); +public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); - private readonly ILogger _logger; +private readonly ILogger _logger; - public ErrorModel(ILogger logger) - { - _logger = logger; - } +public ErrorModel(ILogger logger) +{ + _logger = logger; +} - public void OnGet() - { - RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; - } - } +public void OnGet() +{ + RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; +} } diff --git a/docs/CustomNodesLinks/Pages/Index.razor b/docs/CustomNodesLinks/Pages/Index.razor index 6bcb54eec..65c4336b1 100644 --- a/docs/CustomNodesLinks/Pages/Index.razor +++ b/docs/CustomNodesLinks/Pages/Index.razor @@ -1,11 +1,14 @@ @page "/" +@using Blazor.Diagrams @using Blazor.Diagrams.Core @using Blazor.Diagrams.Core.Geometry @using Blazor.Diagrams.Core.Models @using Blazor.Diagrams.Components +@using Blazor.Diagrams.Core.Options +@using Blazor.Diagrams.Options @using CustomNodesLinks.Models @using CustomNodesLinks.Widgets @@ -19,37 +22,35 @@ or it will not be rendered. 100vh = 100% viewport height -->
- +
@code { - private Diagram _diagram { get; set; } + private BlazorDiagram BlazorDiagram { get; set; } protected override void OnInitialized() { base.OnInitialized(); - var options = new DiagramOptions + var options = new BlazorDiagramOptions { - DeleteKey = "Delete", // What key deletes the selected nodes/links - DefaultNodeComponent = null, // Default component for nodes AllowMultiSelection = true, // Whether to allow multi selection using CTRL - Links = new DiagramLinkOptions + Links = { }, - Zoom = new DiagramZoomOptions + Zoom = { Minimum = 0.5, // Minimum zoom value Inverse = false, // Whether to inverse the direction of the zoom when using the wheel } }; - _diagram = new Diagram(options); + BlazorDiagram = new BlazorDiagram(options); // connect node/link to renderer - _diagram.RegisterModelComponent(); - _diagram.RegisterModelComponent(); + BlazorDiagram.RegisterComponent(); + BlazorDiagram.RegisterComponent(); Setup(); } @@ -59,11 +60,11 @@ or it will not be rendered. var node1 = new DiagramNode("Node 0", new Point(50, 50)); var node2 = new DiagramNode("Node 1", new Point(300, 300)); var node3 = new DiagramNode("Node 2", new Point(300, 50)); - _diagram.Nodes.Add(new[] { node1, node2, node3 }); + BlazorDiagram.Nodes.Add(new[] { node1, node2, node3 }); // use portless links so connection points move around when we move node var link = new DiagramLink($"{node1.Name}-->{node2.Name}", node1, node2); - _diagram.Links.Add(link); + BlazorDiagram.Links.Add(link); } } diff --git a/docs/CustomNodesLinks/Program.cs b/docs/CustomNodesLinks/Program.cs index 7cd4ae325..9c6c3966b 100644 --- a/docs/CustomNodesLinks/Program.cs +++ b/docs/CustomNodesLinks/Program.cs @@ -1,17 +1,16 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Hosting; -namespace CustomNodesLinks +namespace CustomNodesLinks; + +public class Program +{ +public static void Main(string[] args) { - public class Program - { - public static void Main(string[] args) - { - CreateHostBuilder(args).Build().Run(); - } + CreateHostBuilder(args).Build().Run(); +} - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }); - } +public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }); } diff --git a/docs/CustomNodesLinks/Startup.cs b/docs/CustomNodesLinks/Startup.cs index 5ccdae6c6..c233b2e33 100644 --- a/docs/CustomNodesLinks/Startup.cs +++ b/docs/CustomNodesLinks/Startup.cs @@ -4,49 +4,48 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -namespace CustomNodesLinks +namespace CustomNodesLinks; + +public class Startup +{ +public Startup(IConfiguration configuration) +{ + Configuration = configuration; +} + +public IConfiguration Configuration { get; } + +// This method gets called by the runtime. Use this method to add services to the container. +// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 +public void ConfigureServices(IServiceCollection services) +{ + services.AddRazorPages(); + services.AddServerSideBlazor(); +} + +// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. +public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { - public class Startup + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + else { - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public void ConfigureServices(IServiceCollection services) - { - services.AddRazorPages(); - services.AddServerSideBlazor(); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - else - { - app.UseExceptionHandler("/Error"); - // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. - app.UseHsts(); - } - - app.UseHttpsRedirection(); - app.UseStaticFiles(); - - app.UseRouting(); - - app.UseEndpoints(endpoints => - { - endpoints.MapBlazorHub(); - endpoints.MapFallbackToPage("/_Host"); - }); - } + app.UseExceptionHandler("/Error"); + // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. + app.UseHsts(); } + + app.UseHttpsRedirection(); + app.UseStaticFiles(); + + app.UseRouting(); + + app.UseEndpoints(endpoints => + { + endpoints.MapBlazorHub(); + endpoints.MapFallbackToPage("/_Host"); + }); +} } diff --git a/docs/Diagram-Demo/Diagram-Demo.csproj b/docs/Diagram-Demo/Diagram-Demo.csproj index 4b8e0d0a5..7bc16f503 100644 --- a/docs/Diagram-Demo/Diagram-Demo.csproj +++ b/docs/Diagram-Demo/Diagram-Demo.csproj @@ -1,7 +1,7 @@ - net5.0 + net6.0 Diagram_Demo diff --git a/docs/Diagram-Demo/Pages/Diagrams.razor b/docs/Diagram-Demo/Pages/Diagrams.razor index 9951ac8c1..2c56d7ef7 100644 --- a/docs/Diagram-Demo/Pages/Diagrams.razor +++ b/docs/Diagram-Demo/Pages/Diagrams.razor @@ -6,6 +6,9 @@ @using Blazor.Diagrams.Components +@using Blazor.Diagrams.Core.Options +@using Blazor.Diagrams.Options +@using Blazor.Diagrams

Z Blazor Diagrams

@@ -31,21 +34,19 @@ or it will not be rendered. { base.OnInitialized(); - var options = new DiagramOptions + var options = new BlazorDiagramOptions { - DeleteKey = "Delete", // What key deletes the selected nodes/links - DefaultNodeComponent = null, // Default component for nodes AllowMultiSelection = true, // Whether to allow multi selection using CTRL - Links = new DiagramLinkOptions + Links = { }, - Zoom = new DiagramZoomOptions + Zoom = { Minimum = 0.5, // Minimum zoom value Inverse = false, // Whether to inverse the direction of the zoom when using the wheel } }; - Diagram = new Diagram(options); + Diagram = new BlazorDiagram(options); Setup(); } diff --git a/docs/Diagram-Demo/Pages/Error.cshtml.cs b/docs/Diagram-Demo/Pages/Error.cshtml.cs index 0d45fc81b..555cbe763 100644 --- a/docs/Diagram-Demo/Pages/Error.cshtml.cs +++ b/docs/Diagram-Demo/Pages/Error.cshtml.cs @@ -1,32 +1,27 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Threading.Tasks; +using System.Diagnostics; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Logging; -namespace Diagram_Demo.Pages +namespace Diagram_Demo.Pages; + +[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] +[IgnoreAntiforgeryToken] +public class ErrorModel : PageModel { - [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] - [IgnoreAntiforgeryToken] - public class ErrorModel : PageModel - { - public string RequestId { get; set; } + public string RequestId { get; set; } - public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); + public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); - private readonly ILogger _logger; + private readonly ILogger _logger; - public ErrorModel(ILogger logger) - { - _logger = logger; - } + public ErrorModel(ILogger logger) + { + _logger = logger; + } - public void OnGet() - { - RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; - } + public void OnGet() + { + RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; } } diff --git a/docs/Diagram-Demo/Program.cs b/docs/Diagram-Demo/Program.cs index 455a21dc1..f421aa96f 100644 --- a/docs/Diagram-Demo/Program.cs +++ b/docs/Diagram-Demo/Program.cs @@ -1,17 +1,16 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Hosting; -namespace Diagram_Demo +namespace Diagram_Demo; + +public class Program +{ +public static void Main(string[] args) { - public class Program - { - public static void Main(string[] args) - { - CreateHostBuilder(args).Build().Run(); - } + CreateHostBuilder(args).Build().Run(); +} - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }); - } +public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }); } diff --git a/docs/Diagram-Demo/Startup.cs b/docs/Diagram-Demo/Startup.cs index a1e1d8926..a398e3df6 100644 --- a/docs/Diagram-Demo/Startup.cs +++ b/docs/Diagram-Demo/Startup.cs @@ -4,49 +4,48 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -namespace Diagram_Demo +namespace Diagram_Demo; + +public class Startup +{ +public Startup(IConfiguration configuration) +{ + Configuration = configuration; +} + +public IConfiguration Configuration { get; } + +// This method gets called by the runtime. Use this method to add services to the container. +// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 +public void ConfigureServices(IServiceCollection services) +{ + services.AddRazorPages(); + services.AddServerSideBlazor(); +} + +// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. +public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { - public class Startup + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + else { - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public void ConfigureServices(IServiceCollection services) - { - services.AddRazorPages(); - services.AddServerSideBlazor(); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - else - { - app.UseExceptionHandler("/Error"); - // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. - app.UseHsts(); - } - - app.UseHttpsRedirection(); - app.UseStaticFiles(); - - app.UseRouting(); - - app.UseEndpoints(endpoints => - { - endpoints.MapBlazorHub(); - endpoints.MapFallbackToPage("/_Host"); - }); - } + app.UseExceptionHandler("/Error"); + // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. + app.UseHsts(); } + + app.UseHttpsRedirection(); + app.UseStaticFiles(); + + app.UseRouting(); + + app.UseEndpoints(endpoints => + { + endpoints.MapBlazorHub(); + endpoints.MapFallbackToPage("/_Host"); + }); +} } diff --git a/docs/Layouts/Layouts.csproj b/docs/Layouts/Layouts.csproj index 762134e56..3350a9e9e 100644 --- a/docs/Layouts/Layouts.csproj +++ b/docs/Layouts/Layouts.csproj @@ -1,7 +1,7 @@ - net5.0 + net6.0 diff --git a/docs/Layouts/Pages/Error.cshtml.cs b/docs/Layouts/Pages/Error.cshtml.cs index 274e1ca6a..2c40ebbbe 100644 --- a/docs/Layouts/Pages/Error.cshtml.cs +++ b/docs/Layouts/Pages/Error.cshtml.cs @@ -1,32 +1,27 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Threading.Tasks; +using System.Diagnostics; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Logging; -namespace Layouts.Pages +namespace Layouts.Pages; + +[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] +[IgnoreAntiforgeryToken] +public class ErrorModel : PageModel { - [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] - [IgnoreAntiforgeryToken] - public class ErrorModel : PageModel - { - public string RequestId { get; set; } +public string RequestId { get; set; } - public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); +public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); - private readonly ILogger _logger; +private readonly ILogger _logger; - public ErrorModel(ILogger logger) - { - _logger = logger; - } +public ErrorModel(ILogger logger) +{ + _logger = logger; +} - public void OnGet() - { - RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; - } - } +public void OnGet() +{ + RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; +} } diff --git a/docs/Layouts/Pages/Index.razor b/docs/Layouts/Pages/Index.razor index f21525988..9f950b2ae 100644 --- a/docs/Layouts/Pages/Index.razor +++ b/docs/Layouts/Pages/Index.razor @@ -3,11 +3,15 @@ @using Blazor.Diagrams.Core @using Blazor.Diagrams.Core.Geometry @using Blazor.Diagrams.Core.Models +@using Blazor.Diagrams.Core.Models.Base @using QG = QuikGraph @using Blazor.Diagrams.Components +@using Blazor.Diagrams.Core.Options @using GraphShape.Algorithms.Layout +@using Blazor.Diagrams +@using Blazor.Diagrams.Options

Hello, World of Layouts!

@@ -19,111 +23,105 @@ or it will not be rendered. 100vh = 100% viewport height -->
- - - + + +
- - @foreach (var algo in new GraphShape.Algorithms.Layout.StandardLayoutAlgorithmFactory, QG.IBidirectionalGraph>>().AlgorithmTypes) - { - @algo - } - - - Go! + + @foreach (var algo in new GraphShape.Algorithms.Layout.StandardLayoutAlgorithmFactory, QG.IBidirectionalGraph>>().AlgorithmTypes) + { + @algo + } + + + Go!
@code { - private Diagram _diagram { get; set; } - - private string _layout; + private Diagram _diagram { get; set; } - protected override void OnInitialized() - { - base.OnInitialized(); + private string _layout; - var options = new DiagramOptions + protected override void OnInitialized() { - DeleteKey = "Delete", // What key deletes the selected nodes/links - DefaultNodeComponent = null, // Default component for nodes - AllowMultiSelection = true, // Whether to allow multi selection using CTRL - Links = new DiagramLinkOptions - { - }, - Zoom = new DiagramZoomOptions + base.OnInitialized(); + + var options = new BlazorDiagramOptions + { + AllowMultiSelection = true, + Zoom = { - Minimum = 0.5, // Minimum zoom value - Inverse = false, // Whether to inverse the direction of the zoom when using the wheel - } - }; - _diagram = new Diagram(options); - - Setup(); - } - - private void Setup() - { - var node1 = NewNode(50, 50); - var node2 = NewNode(300, 300); - var node3 = NewNode(300, 50); - _diagram.Nodes.Add(new[] { node1, node2, node3 }); - - // use portless nodes so connection points can move around after layout - _diagram.Links.Add(new LinkModel(node1, node2)); - } - - private static NodeModel NewNode(double x, double y) - { - var node = new NodeModel(Guid.NewGuid().ToString(), new Point(x, y)); - return node; - } - - private void OnLayout(string layout) - { - if (string.IsNullOrWhiteSpace(layout)) + Minimum = 0.5 + } // Whether to allow multi selection using CTRL + }; + _diagram = new BlazorDiagram(options); + + Setup(); + } + + private void Setup() { - return; + var node1 = NewNode(50, 50); + var node2 = NewNode(300, 300); + var node3 = NewNode(300, 50); + _diagram.Nodes.Add(new[] { node1, node2, node3 }); + + // use portless nodes so connection points can move around after layout + _diagram.Links.Add(new LinkModel(node1, node2)); } - // convert Z.Blazor.Diagram to QuikGraph - var graph = new QG.BidirectionalGraph>(); - var nodes = _diagram.Nodes.OfType().ToList(); - var edges = _diagram.Links.OfType() - .Select(lm => - { - var source = nodes.Single(dn => dn.Id == lm.SourceNode.Id); - var target = nodes.Single(dn => dn.Id == lm?.TargetNode?.Id); - return new QG.Edge(source, target); - }) - .ToList(); - graph.AddVertexRange(nodes); - graph.AddEdgeRange(edges); - - // run GraphShape algorithm - var positions = nodes.ToDictionary(nm => nm, dn => new GraphShape.Point(dn.Position.X, dn.Position.Y)); - var sizes = nodes.ToDictionary(nm => nm, dn => new GraphShape.Size(dn.Size?.Width ?? 100, dn.Size?.Height ?? 100)); - var layoutCtx = new LayoutContext, QG.BidirectionalGraph>>(graph, positions, sizes, LayoutMode.Simple); - var algoFact = new StandardLayoutAlgorithmFactory, QG.BidirectionalGraph>>(); - var algo = algoFact.CreateAlgorithm(layout, layoutCtx, null); - - algo.Compute(); - - // update NodeModel positions - try + private static NodeModel NewNode(double x, double y) { - _diagram.SuspendRefresh = true; - foreach (var vertPos in algo.VerticesPositions) - { - // NOTE; have to use SetPosition which takes care of updating everything - vertPos.Key.SetPosition(vertPos.Value.X, vertPos.Value.Y); - } + var node = new NodeModel(Guid.NewGuid().ToString(), new Point(x, y)); + return node; } - finally + + private void OnLayout(string layout) { - _diagram.SuspendRefresh = false; + if (string.IsNullOrWhiteSpace(layout)) + { + return; + } + + // convert Z.Blazor.Diagram to QuikGraph + var graph = new QG.BidirectionalGraph>(); + var nodes = _diagram.Nodes.OfType().ToList(); + var edges = _diagram.Links.OfType() + .Select(lm => + { + var source = nodes.Single(dn => dn.Id == (lm.Source.Model as Model).Id); + var target = nodes.Single(dn => dn.Id == (lm.Target.Model as Model)?.Id); + return new QG.Edge(source, target); + }) + .ToList(); + graph.AddVertexRange(nodes); + graph.AddEdgeRange(edges); + + // run GraphShape algorithm + var positions = nodes.ToDictionary(nm => nm, dn => new GraphShape.Point(dn.Position.X, dn.Position.Y)); + var sizes = nodes.ToDictionary(nm => nm, dn => new GraphShape.Size(dn.Size?.Width ?? 100, dn.Size?.Height ?? 100)); + var layoutCtx = new LayoutContext, QG.BidirectionalGraph>>(graph, positions, sizes, LayoutMode.Simple); + var algoFact = new StandardLayoutAlgorithmFactory, QG.BidirectionalGraph>>(); + var algo = algoFact.CreateAlgorithm(layout, layoutCtx, null); + + algo.Compute(); + + // update NodeModel positions + try + { + _diagram.SuspendRefresh = true; + foreach (var vertPos in algo.VerticesPositions) + { + // NOTE; have to use SetPosition which takes care of updating everything + vertPos.Key.SetPosition(vertPos.Value.X, vertPos.Value.Y); + } + } + finally + { + _diagram.SuspendRefresh = false; + } } - } } diff --git a/docs/Layouts/Program.cs b/docs/Layouts/Program.cs index 71e2194a2..57bc41d32 100644 --- a/docs/Layouts/Program.cs +++ b/docs/Layouts/Program.cs @@ -1,17 +1,16 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Hosting; -namespace Layouts +namespace Layouts; + +public class Program +{ +public static void Main(string[] args) { - public class Program - { - public static void Main(string[] args) - { - CreateHostBuilder(args).Build().Run(); - } + CreateHostBuilder(args).Build().Run(); +} - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }); - } +public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }); } diff --git a/docs/Layouts/Startup.cs b/docs/Layouts/Startup.cs index 66cf271b8..cea43ff5f 100644 --- a/docs/Layouts/Startup.cs +++ b/docs/Layouts/Startup.cs @@ -5,52 +5,51 @@ using Microsoft.Extensions.Hosting; using MatBlazor; -namespace Layouts +namespace Layouts; + +public class Startup +{ +public Startup(IConfiguration configuration) +{ + Configuration = configuration; +} + +public IConfiguration Configuration { get; } + +// This method gets called by the runtime. Use this method to add services to the container. +// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 +public void ConfigureServices(IServiceCollection services) +{ + services.AddRazorPages(); + services.AddServerSideBlazor(); + services + //.AddFontAwesomeIcons() + .AddMatBlazor(); +} + +// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. +public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { - public class Startup + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + else { - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public void ConfigureServices(IServiceCollection services) - { - services.AddRazorPages(); - services.AddServerSideBlazor(); - services - //.AddFontAwesomeIcons() - .AddMatBlazor(); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - else - { - app.UseExceptionHandler("/Error"); - // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. - app.UseHsts(); - } - - app.UseHttpsRedirection(); - app.UseStaticFiles(); - - app.UseRouting(); - - app.UseEndpoints(endpoints => - { - endpoints.MapBlazorHub(); - endpoints.MapFallbackToPage("/_Host"); - }); - } + app.UseExceptionHandler("/Error"); + // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. + app.UseHsts(); } + + app.UseHttpsRedirection(); + app.UseStaticFiles(); + + app.UseRouting(); + + app.UseEndpoints(endpoints => + { + endpoints.MapBlazorHub(); + endpoints.MapFallbackToPage("/_Host"); + }); +} } diff --git a/samples/ServerSide/Program.cs b/samples/ServerSide/Program.cs index 26ad3b4c7..a6591ca8d 100644 --- a/samples/ServerSide/Program.cs +++ b/samples/ServerSide/Program.cs @@ -1,28 +1,19 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -namespace ServerSide +namespace ServerSide; + +public class Program { - public class Program + public static void Main(string[] args) { - public static void Main(string[] args) - { - CreateHostBuilder(args).Build().Run(); - } - - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(); - }); + CreateHostBuilder(args).Build().Run(); } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); } diff --git a/samples/ServerSide/ServerSide.csproj b/samples/ServerSide/ServerSide.csproj index 89612adab..7a5552fa1 100644 --- a/samples/ServerSide/ServerSide.csproj +++ b/samples/ServerSide/ServerSide.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1 + net6.0 diff --git a/samples/ServerSide/Startup.cs b/samples/ServerSide/Startup.cs index d46344395..579163f80 100644 --- a/samples/ServerSide/Startup.cs +++ b/samples/ServerSide/Startup.cs @@ -5,46 +5,45 @@ using Microsoft.Extensions.Hosting; using SharedDemo; -namespace ServerSide +namespace ServerSide; + +public class Startup { - public class Startup + public Startup(IConfiguration configuration) { - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } + Configuration = configuration; + } - public IConfiguration Configuration { get; } + public IConfiguration Configuration { get; } + + public void ConfigureServices(IServiceCollection services) + { + services.AddRazorPages(); + services.AddServerSideBlazor(); + services.AddSingleton(); + } - public void ConfigureServices(IServiceCollection services) + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) { - services.AddRazorPages(); - services.AddServerSideBlazor(); - services.AddSingleton(); + app.UseDeveloperExceptionPage(); } - - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + else { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - else - { - app.UseExceptionHandler("/Error"); - app.UseHsts(); - } - - app.UseHttpsRedirection(); - app.UseStaticFiles(); - - app.UseRouting(); - - app.UseEndpoints(endpoints => - { - endpoints.MapBlazorHub(); - endpoints.MapFallbackToPage("/_Host"); - }); + app.UseExceptionHandler("/Error"); + app.UseHsts(); } + + app.UseHttpsRedirection(); + app.UseStaticFiles(); + + app.UseRouting(); + + app.UseEndpoints(endpoints => + { + endpoints.MapBlazorHub(); + endpoints.MapFallbackToPage("/_Host"); + }); } } diff --git a/samples/SharedDemo/Demos/Algorithms/ReconnectLinksToClosestPorts.razor b/samples/SharedDemo/Demos/Algorithms/ReconnectLinksToClosestPorts.razor index 9d4b341e0..ad3899a6d 100644 --- a/samples/SharedDemo/Demos/Algorithms/ReconnectLinksToClosestPorts.razor +++ b/samples/SharedDemo/Demos/Algorithms/ReconnectLinksToClosestPorts.razor @@ -18,10 +18,11 @@ - + - + \ No newline at end of file diff --git a/samples/SharedDemo/Demos/Algorithms/ReconnectLinksToClosestPorts.razor.cs b/samples/SharedDemo/Demos/Algorithms/ReconnectLinksToClosestPorts.razor.cs index 12c43ee8f..bb3303a37 100644 --- a/samples/SharedDemo/Demos/Algorithms/ReconnectLinksToClosestPorts.razor.cs +++ b/samples/SharedDemo/Demos/Algorithms/ReconnectLinksToClosestPorts.razor.cs @@ -1,39 +1,38 @@ -using Blazor.Diagrams.Algorithms; -using Blazor.Diagrams.Core; +using Blazor.Diagrams; +using Blazor.Diagrams.Algorithms; +using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Core.Models; using Microsoft.AspNetCore.Components; -using Blazor.Diagrams.Core.Geometry; -namespace SharedDemo.Demos.Algorithms +namespace SharedDemo.Demos.Algorithms; + +public class ReconnectLinksToClosestPortsComponent : ComponentBase { - public class ReconnectLinksToClosestPortsComponent : ComponentBase - { - protected readonly Diagram diagram = new Diagram(); + protected readonly BlazorDiagram BlazorDiagram = new BlazorDiagram(); - protected override void OnInitialized() - { - base.OnInitialized(); + protected override void OnInitialized() + { + base.OnInitialized(); - var node1 = NewNode(50, 50); - var node2 = NewNode(300, 300); - var node3 = NewNode(300, 50); - diagram.Links.Add(new LinkModel(node1.GetPort(PortAlignment.Top), node2.GetPort(PortAlignment.Right))); - diagram.Links.Add(new LinkModel(node1.GetPort(PortAlignment.Bottom), node3.GetPort(PortAlignment.Top))); - diagram.Nodes.Add(new[] { node1, node2, node3 }); - } + var node1 = NewNode(50, 50); + var node2 = NewNode(300, 300); + var node3 = NewNode(300, 50); + BlazorDiagram.Links.Add(new LinkModel(node1.GetPort(PortAlignment.Top), node2.GetPort(PortAlignment.Right))); + BlazorDiagram.Links.Add(new LinkModel(node1.GetPort(PortAlignment.Bottom), node3.GetPort(PortAlignment.Top))); + BlazorDiagram.Nodes.Add(new[] { node1, node2, node3 }); + } - protected void ReconnectLinks() => diagram.ReconnectLinksToClosestPorts(); + protected void ReconnectLinks() => BlazorDiagram.ReconnectLinksToClosestPorts(); - private NodeModel NewNode(double x, double y) - { - var node = new NodeModel(new Point(x, y)); - node.AddPort(PortAlignment.Bottom); - node.AddPort(PortAlignment.Top); - node.AddPort(PortAlignment.Left); - node.AddPort(PortAlignment.Right); - return node; - } + private NodeModel NewNode(double x, double y) + { + var node = new NodeModel(new Point(x, y)); + node.AddPort(PortAlignment.Bottom); + node.AddPort(PortAlignment.Top); + node.AddPort(PortAlignment.Left); + node.AddPort(PortAlignment.Right); + return node; } } diff --git a/samples/SharedDemo/Demos/BotAnswerNode.cs b/samples/SharedDemo/Demos/BotAnswerNode.cs index b345facbe..3a34c9b59 100644 --- a/samples/SharedDemo/Demos/BotAnswerNode.cs +++ b/samples/SharedDemo/Demos/BotAnswerNode.cs @@ -1,12 +1,11 @@ using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Core.Models; -namespace SharedDemo.Demos +namespace SharedDemo.Demos; + +public class BotAnswerNode : NodeModel { - public class BotAnswerNode : NodeModel - { - public BotAnswerNode(Point position = null) : base(position) { } + public BotAnswerNode(Point position = null) : base(position) { } - public string Answer { get; set; } - } + public string Answer { get; set; } } diff --git a/samples/SharedDemo/Demos/BotAnswerWidget.razor b/samples/SharedDemo/Demos/BotAnswerWidget.razor index a2c6ad938..ed540e1aa 100644 --- a/samples/SharedDemo/Demos/BotAnswerWidget.razor +++ b/samples/SharedDemo/Demos/BotAnswerWidget.razor @@ -6,16 +6,16 @@ + @onpointerdown:stopPropagation + @onpointerup:stopPropagation + @onpointermove:stopPropagation /> @foreach (var port in Node.Ports) { - + } diff --git a/samples/SharedDemo/Demos/CustomGroup/CustomGroupModel.cs b/samples/SharedDemo/Demos/CustomGroup/CustomGroupModel.cs index 021431e8b..65d949d68 100644 --- a/samples/SharedDemo/Demos/CustomGroup/CustomGroupModel.cs +++ b/samples/SharedDemo/Demos/CustomGroup/CustomGroupModel.cs @@ -1,15 +1,14 @@ using Blazor.Diagrams.Core.Models; -namespace SharedDemo.Demos.CustomGroup +namespace SharedDemo.Demos.CustomGroup; + +public class CustomGroupModel : GroupModel { - public class CustomGroupModel : GroupModel + public CustomGroupModel(NodeModel[] children, string title, byte padding = 30) + : base(children, padding) { - public CustomGroupModel(NodeModel[] children, string title, byte padding = 30) - : base(children, padding) - { - Title = title; - } - - public string Title { get; } + Title = title; } + + public string Title { get; } } diff --git a/samples/SharedDemo/Demos/CustomGroup/CustomGroupWidget.razor b/samples/SharedDemo/Demos/CustomGroup/CustomGroupWidget.razor index d87d0f964..82d7aa229 100644 --- a/samples/SharedDemo/Demos/CustomGroup/CustomGroupWidget.razor +++ b/samples/SharedDemo/Demos/CustomGroup/CustomGroupWidget.razor @@ -1,8 +1,12 @@ - - @Group.Title - - - +@Group.Title + + + +@foreach (var port in Group.Ports) +{ + +} + @code { [Parameter] public CustomGroupModel Group { get; set; } diff --git a/samples/SharedDemo/Demos/CustomGroup/Demo.razor b/samples/SharedDemo/Demos/CustomGroup/Demo.razor index cff05d4d7..f1c12d705 100644 --- a/samples/SharedDemo/Demos/CustomGroup/Demo.razor +++ b/samples/SharedDemo/Demos/CustomGroup/Demo.razor @@ -2,6 +2,6 @@ @layout DemoLayout @inject LayoutData LayoutData - + \ No newline at end of file diff --git a/samples/SharedDemo/Demos/CustomGroup/Demo.razor.cs b/samples/SharedDemo/Demos/CustomGroup/Demo.razor.cs index 79addca7f..edfcbc11d 100644 --- a/samples/SharedDemo/Demos/CustomGroup/Demo.razor.cs +++ b/samples/SharedDemo/Demos/CustomGroup/Demo.razor.cs @@ -1,42 +1,43 @@ -using Blazor.Diagrams.Core; +using Blazor.Diagrams; using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Core.Models; -namespace SharedDemo.Demos.CustomGroup +namespace SharedDemo.Demos.CustomGroup; + +partial class Demo { - partial class Demo + private readonly BlazorDiagram _blazorDiagram = new BlazorDiagram(); + + protected override void OnInitialized() + { + base.OnInitialized(); + + LayoutData.Title = "Custom group"; + LayoutData.Info = "Creating your own custom groups is very easy!"; + LayoutData.DataChanged(); + + _blazorDiagram.Options.LinksLayerOrder = 2; + _blazorDiagram.Options.NodesLayerOrder = 1; + _blazorDiagram.RegisterComponent(); + + var node1 = NewNode(50, 50); + var node2 = NewNode(300, 300); + var node3 = NewNode(500, 100); + + _blazorDiagram.Nodes.Add(new[] { node1, node2, node3 }); + _blazorDiagram.Groups.Add(new CustomGroupModel(new[] { node2, node3 }, "Group 1")); + + _blazorDiagram.Links.Add(new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left))); + _blazorDiagram.Links.Add(new LinkModel(node2.GetPort(PortAlignment.Right), node3.GetPort(PortAlignment.Left))); + } + + private NodeModel NewNode(double x, double y) { - private readonly Diagram _diagram = new Diagram(); - - protected override void OnInitialized() - { - base.OnInitialized(); - - LayoutData.Title = "Custom group"; - LayoutData.Info = "Creating your own custom groups is very easy!"; - LayoutData.DataChanged(); - - _diagram.RegisterModelComponent(); - - var node1 = NewNode(50, 50); - var node2 = NewNode(300, 300); - var node3 = NewNode(500, 100); - - _diagram.Nodes.Add(new[] { node1, node2, node3 }); - _diagram.AddGroup(new CustomGroupModel(new[] { node2, node3 }, "Group 1")); - - _diagram.Links.Add(new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left))); - _diagram.Links.Add(new LinkModel(node2.GetPort(PortAlignment.Right), node3.GetPort(PortAlignment.Left))); - } - - private NodeModel NewNode(double x, double y) - { - var node = new NodeModel(new Point(x, y)); - node.AddPort(PortAlignment.Bottom); - node.AddPort(PortAlignment.Top); - node.AddPort(PortAlignment.Left); - node.AddPort(PortAlignment.Right); - return node; - } + var node = new NodeModel(new Point(x, y)); + node.AddPort(PortAlignment.Bottom); + node.AddPort(PortAlignment.Top); + node.AddPort(PortAlignment.Left); + node.AddPort(PortAlignment.Right); + return node; } } diff --git a/samples/SharedDemo/Demos/CustomLink/Demo.razor b/samples/SharedDemo/Demos/CustomLink/Demo.razor index bd20c21ca..1ac8f54e2 100644 --- a/samples/SharedDemo/Demos/CustomLink/Demo.razor +++ b/samples/SharedDemo/Demos/CustomLink/Demo.razor @@ -2,6 +2,6 @@ @layout DemoLayout @inject LayoutData LayoutData - + \ No newline at end of file diff --git a/samples/SharedDemo/Demos/CustomLink/Demo.razor.cs b/samples/SharedDemo/Demos/CustomLink/Demo.razor.cs index 9d506ff21..06e0a69d5 100644 --- a/samples/SharedDemo/Demos/CustomLink/Demo.razor.cs +++ b/samples/SharedDemo/Demos/CustomLink/Demo.razor.cs @@ -1,41 +1,40 @@ -using Blazor.Diagrams.Core; +using Blazor.Diagrams; using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Core.Models; -namespace SharedDemo.Demos.CustomLink +namespace SharedDemo.Demos.CustomLink; + +partial class Demo { - partial class Demo + private readonly BlazorDiagram _blazorDiagram = new BlazorDiagram(); + + protected override void OnInitialized() + { + base.OnInitialized(); + + LayoutData.Title = "Custom link"; + LayoutData.Info = "Creating your own custom links is very easy!"; + LayoutData.DataChanged(); + + _blazorDiagram.RegisterComponent(); + // Also usable: _diagram.Options.Links.DefaultLinkComponent = typeof(ThickLink); + + var node1 = NewNode(50, 50); + var node2 = NewNode(300, 300); + var node3 = NewNode(500, 50); + + _blazorDiagram.Nodes.Add(new[] { node1, node2, node3 }); + _blazorDiagram.Links.Add(new ThickLink(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left))); + _blazorDiagram.Links.Add(new ThickLink(node2.GetPort(PortAlignment.Right), node3.GetPort(PortAlignment.Left))); + } + + private NodeModel NewNode(double x, double y) { - private readonly Diagram _diagram = new Diagram(); - - protected override void OnInitialized() - { - base.OnInitialized(); - - LayoutData.Title = "Custom link"; - LayoutData.Info = "Creating your own custom links is very easy!"; - LayoutData.DataChanged(); - - _diagram.RegisterModelComponent(); - // Also usable: _diagram.Options.Links.DefaultLinkComponent = typeof(ThickLink); - - var node1 = NewNode(50, 50); - var node2 = NewNode(300, 300); - var node3 = NewNode(500, 50); - - _diagram.Nodes.Add(new[] { node1, node2, node3 }); - _diagram.Links.Add(new ThickLink(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left))); - _diagram.Links.Add(new ThickLink(node2.GetPort(PortAlignment.Right), node3.GetPort(PortAlignment.Left))); - } - - private NodeModel NewNode(double x, double y) - { - var node = new NodeModel(new Point(x, y)); - node.AddPort(PortAlignment.Bottom); - node.AddPort(PortAlignment.Top); - node.AddPort(PortAlignment.Left); - node.AddPort(PortAlignment.Right); - return node; - } + var node = new NodeModel(new Point(x, y)); + node.AddPort(PortAlignment.Bottom); + node.AddPort(PortAlignment.Top); + node.AddPort(PortAlignment.Left); + node.AddPort(PortAlignment.Right); + return node; } } diff --git a/samples/SharedDemo/Demos/CustomLink/ThickLink.cs b/samples/SharedDemo/Demos/CustomLink/ThickLink.cs index 4156c18cf..1fb8e285e 100644 --- a/samples/SharedDemo/Demos/CustomLink/ThickLink.cs +++ b/samples/SharedDemo/Demos/CustomLink/ThickLink.cs @@ -1,9 +1,8 @@ using Blazor.Diagrams.Core.Models; -namespace SharedDemo.Demos.CustomLink +namespace SharedDemo.Demos.CustomLink; + +public class ThickLink : LinkModel { - public class ThickLink : LinkModel - { - public ThickLink(PortModel sourcePort, PortModel targetPort = null) : base(sourcePort, targetPort) { } - } + public ThickLink(PortModel sourcePort, PortModel targetPort = null) : base(sourcePort, targetPort) { } } diff --git a/samples/SharedDemo/Demos/CustomLink/ThickLinkWidget.razor b/samples/SharedDemo/Demos/CustomLink/ThickLinkWidget.razor index e8902ec2a..0a0e68fb3 100644 --- a/samples/SharedDemo/Demos/CustomLink/ThickLinkWidget.razor +++ b/samples/SharedDemo/Demos/CustomLink/ThickLinkWidget.razor @@ -3,9 +3,19 @@ public LinkModel Link { get; set; } } - \ No newline at end of file diff --git a/samples/SharedDemo/Demos/CustomNode.razor b/samples/SharedDemo/Demos/CustomNode.razor index e5992c69a..7337da801 100644 --- a/samples/SharedDemo/Demos/CustomNode.razor +++ b/samples/SharedDemo/Demos/CustomNode.razor @@ -14,6 +14,6 @@ } } - + diff --git a/samples/SharedDemo/Demos/CustomNode.razor.cs b/samples/SharedDemo/Demos/CustomNode.razor.cs index 55a4e4fca..6d4ff99e2 100644 --- a/samples/SharedDemo/Demos/CustomNode.razor.cs +++ b/samples/SharedDemo/Demos/CustomNode.razor.cs @@ -1,35 +1,34 @@ -using Blazor.Diagrams.Core; -using Blazor.Diagrams.Core.Models; +using Blazor.Diagrams.Core.Models; using Microsoft.AspNetCore.Components; using Blazor.Diagrams.Core.Geometry; +using Blazor.Diagrams; -namespace SharedDemo.Demos +namespace SharedDemo.Demos; + +public class CustomNodeComponent : ComponentBase { - public class CustomNodeComponent : ComponentBase - { - protected readonly Diagram diagram = new Diagram(); + protected readonly BlazorDiagram BlazorDiagram = new BlazorDiagram(); - protected override void OnInitialized() - { - base.OnInitialized(); + protected override void OnInitialized() + { + base.OnInitialized(); - diagram.RegisterModelComponent(); + BlazorDiagram.RegisterComponent(); - var node = new NodeModel(new Point(20, 20)); - node.AddPort(PortAlignment.Top); - node.AddPort(PortAlignment.Right); - node.AddPort(PortAlignment.Bottom); - node.AddPort(PortAlignment.Left); + var node = new NodeModel(new Point(20, 20)); + node.AddPort(PortAlignment.Top); + node.AddPort(PortAlignment.Right); + node.AddPort(PortAlignment.Bottom); + node.AddPort(PortAlignment.Left); - diagram.Nodes.Add(new[] { node, NewNode(100, 100), NewNode(300, 300) }); - } + BlazorDiagram.Nodes.Add(new[] { node, NewNode(100, 100), NewNode(300, 300) }); + } - private BotAnswerNode NewNode(double x, double y) - { - var node = new BotAnswerNode(new Point(x, y)); - node.AddPort(PortAlignment.Top); - node.AddPort(PortAlignment.Bottom); - return node; - } + private BotAnswerNode NewNode(double x, double y) + { + var node = new BotAnswerNode(new Point(x, y)); + node.AddPort(PortAlignment.Top); + node.AddPort(PortAlignment.Bottom); + return node; } } diff --git a/samples/SharedDemo/Demos/CustomPort/ColoredPort.cs b/samples/SharedDemo/Demos/CustomPort/ColoredPort.cs index 420d5f434..f83a54f40 100644 --- a/samples/SharedDemo/Demos/CustomPort/ColoredPort.cs +++ b/samples/SharedDemo/Demos/CustomPort/ColoredPort.cs @@ -1,27 +1,30 @@ using Blazor.Diagrams.Core.Models; +using Blazor.Diagrams.Core.Models.Base; -namespace SharedDemo.Demos.CustomPort +namespace SharedDemo.Demos.CustomPort; + +public class ColoredPort : PortModel { - public class ColoredPort : PortModel + public ColoredPort(NodeModel parent, PortAlignment alignment, bool isRed) : base(parent, alignment, null, null) { - public ColoredPort(NodeModel parent, PortAlignment alignment, bool isRed) : base(parent, alignment, null, null) - { - IsRed = isRed; - } + IsRed = isRed; + } - public bool IsRed { get; set; } + public bool IsRed { get; set; } - public override bool CanAttachTo(PortModel port) - { - // Checks for same-node/port attachements - if (!base.CanAttachTo(port)) - return false; + public override bool CanAttachTo(ILinkable other) + { + if (other is not PortModel port) + return false; + + // Checks for same-node/port attachments + if (!base.CanAttachTo(port)) + return false; - // Only able to attach to the same port type - if (!(port is ColoredPort cp)) - return false; + // Only able to attach to the same port type + if (port is not ColoredPort cp) + return false; - return IsRed == cp.IsRed; - } + return IsRed == cp.IsRed; } } diff --git a/samples/SharedDemo/Demos/CustomPort/Demo.razor b/samples/SharedDemo/Demos/CustomPort/Demo.razor index b8675208a..d6ef4f590 100644 --- a/samples/SharedDemo/Demos/CustomPort/Demo.razor +++ b/samples/SharedDemo/Demos/CustomPort/Demo.razor @@ -2,6 +2,6 @@ @layout DemoLayout @inject LayoutData LayoutData - + \ No newline at end of file diff --git a/samples/SharedDemo/Demos/CustomPort/Demo.razor.cs b/samples/SharedDemo/Demos/CustomPort/Demo.razor.cs index 54adfc292..12708c81f 100644 --- a/samples/SharedDemo/Demos/CustomPort/Demo.razor.cs +++ b/samples/SharedDemo/Demos/CustomPort/Demo.razor.cs @@ -1,36 +1,35 @@ -using Blazor.Diagrams.Core; -using Blazor.Diagrams.Core.Models; +using Blazor.Diagrams; using Blazor.Diagrams.Core.Geometry; +using Blazor.Diagrams.Core.Models; -namespace SharedDemo.Demos.CustomPort +namespace SharedDemo.Demos.CustomPort; + +partial class Demo { - partial class Demo - { - private readonly Diagram _diagram = new Diagram(); + private readonly BlazorDiagram _blazorDiagram = new BlazorDiagram(); - protected override void OnInitialized() - { - base.OnInitialized(); + protected override void OnInitialized() + { + base.OnInitialized(); - LayoutData.Title = "Custom port"; - LayoutData.Info = "Creating your own custom ports is very easy!
" + - "In this example, you can only attach links from/to ports with the same color."; - LayoutData.DataChanged(); + LayoutData.Title = "Custom port"; + LayoutData.Info = "Creating your own custom ports is very easy!
" + + "In this example, you can only attach links from/to ports with the same color."; + LayoutData.DataChanged(); - _diagram.Options.DefaultNodeComponent = typeof(ColoredNodeWidget); + _blazorDiagram.RegisterComponent(replace: true); - var node1 = NewNode(50, 50); - var node2 = NewNode(300, 300); - _diagram.Nodes.Add(new[] { node1, node2, NewNode(500, 50) }); - _diagram.Links.Add(new LinkModel(node1.GetPort(PortAlignment.Top), node2.GetPort(PortAlignment.Top))); - } + var node1 = NewNode(50, 50); + var node2 = NewNode(300, 300); + _blazorDiagram.Nodes.Add(new[] { node1, node2, NewNode(500, 50) }); + _blazorDiagram.Links.Add(new LinkModel(node1.GetPort(PortAlignment.Top), node2.GetPort(PortAlignment.Top))); + } - private NodeModel NewNode(double x, double y) - { - var node = new NodeModel(new Point(x, y)); - node.AddPort(new ColoredPort(node, PortAlignment.Top, true)); - node.AddPort(new ColoredPort(node, PortAlignment.Left, false)); - return node; - } + private NodeModel NewNode(double x, double y) + { + var node = new NodeModel(new Point(x, y)); + node.AddPort(new ColoredPort(node, PortAlignment.Top, true)); + node.AddPort(new ColoredPort(node, PortAlignment.Left, false)); + return node; } } diff --git a/samples/SharedDemo/Demos/CustomSvgGroup/CustomSvgGroupModel.cs b/samples/SharedDemo/Demos/CustomSvgGroup/CustomSvgGroupModel.cs new file mode 100644 index 000000000..002945171 --- /dev/null +++ b/samples/SharedDemo/Demos/CustomSvgGroup/CustomSvgGroupModel.cs @@ -0,0 +1,12 @@ +using Blazor.Diagrams.Core.Models; +using Blazor.Diagrams.Models; + +namespace SharedDemo.Demos.CustomSvgGroup; + +public class CustomSvgGroupModel : SvgGroupModel +{ + public CustomSvgGroupModel(NodeModel[] children, string title, byte padding = 30) : base(children, padding) + { + Title = title; + } +} diff --git a/samples/SharedDemo/Demos/CustomSvgGroup/CustomSvgGroupWidget.razor b/samples/SharedDemo/Demos/CustomSvgGroup/CustomSvgGroupWidget.razor new file mode 100644 index 000000000..5fba8be18 --- /dev/null +++ b/samples/SharedDemo/Demos/CustomSvgGroup/CustomSvgGroupWidget.razor @@ -0,0 +1,20 @@ +@{ + var rectX = Group.Size.Width / 2 - 50; + var textX = rectX + 50; + var textY = -60 + 25.0; +} + + +@Group.Title + + + +@foreach (var port in Group.Ports) +{ + +} + + +@code { + [Parameter] public CustomSvgGroupModel Group { get; set; } +} diff --git a/samples/SharedDemo/Demos/CustomSvgGroup/Demo.razor b/samples/SharedDemo/Demos/CustomSvgGroup/Demo.razor new file mode 100644 index 000000000..a5a181249 --- /dev/null +++ b/samples/SharedDemo/Demos/CustomSvgGroup/Demo.razor @@ -0,0 +1,7 @@ +@page "/demos/custom-svg-group" +@layout DemoLayout +@inject LayoutData LayoutData + + + + \ No newline at end of file diff --git a/samples/SharedDemo/Demos/CustomSvgGroup/Demo.razor.cs b/samples/SharedDemo/Demos/CustomSvgGroup/Demo.razor.cs new file mode 100644 index 000000000..50a419aed --- /dev/null +++ b/samples/SharedDemo/Demos/CustomSvgGroup/Demo.razor.cs @@ -0,0 +1,44 @@ +using Blazor.Diagrams; +using Blazor.Diagrams.Core.Geometry; +using Blazor.Diagrams.Core.Models; +using Blazor.Diagrams.Models; +using SharedDemo.Demos.Nodes; + +namespace SharedDemo.Demos.CustomSvgGroup; + +partial class Demo +{ + private readonly BlazorDiagram _blazorDiagram = new BlazorDiagram(); + + protected override void OnInitialized() + { + base.OnInitialized(); + + LayoutData.Title = "Custom SVG group"; + LayoutData.Info = "Creating your own custom svg groups is very easy!"; + LayoutData.DataChanged(); + + _blazorDiagram.RegisterComponent(); + _blazorDiagram.RegisterComponent(); + + var node1 = NewNode(50, 50); + var node2 = NewNode(300, 300); + var node3 = NewNode(500, 100); + + _blazorDiagram.Nodes.Add(new[] { node1, node2, node3 }); + _blazorDiagram.Groups.Add(new CustomSvgGroupModel(new[] { node2, node3 }, "Group 1")); + + _blazorDiagram.Links.Add(new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left))); + _blazorDiagram.Links.Add(new LinkModel(node2.GetPort(PortAlignment.Right), node3.GetPort(PortAlignment.Left))); + } + + private NodeModel NewNode(double x, double y) + { + var node = new SvgNodeModel(new Point(x, y)); + node.AddPort(PortAlignment.Bottom); + node.AddPort(PortAlignment.Top); + node.AddPort(PortAlignment.Left); + node.AddPort(PortAlignment.Right); + return node; + } +} diff --git a/samples/SharedDemo/Demos/DevTests.razor b/samples/SharedDemo/Demos/DevTests.razor new file mode 100644 index 000000000..1957abd4d --- /dev/null +++ b/samples/SharedDemo/Demos/DevTests.razor @@ -0,0 +1,99 @@ +@page "/demos/dynamic-anchor" +@layout DemoLayout +@using Blazor.Diagrams +@using Blazor.Diagrams.Core.Anchors +@using Blazor.Diagrams.Core.Controls +@using Blazor.Diagrams.Core.PathGenerators +@using Blazor.Diagrams.Core.Positions +@using Blazor.Diagrams.Core.Controls.Default + + + + + +@code { + private BlazorDiagram _blazorDiagram = new BlazorDiagram(); + + protected override void OnInitialized() + { + var node1 = NewNode(100, 100); + var node2 = NewNode(300, 100); + var node3 = NewNode(500, 250); + + var providers1 = new IPositionProvider[] + { + new BoundsBasedPositionProvider(0.5, 0.0, 0, -10), // top + new BoundsBasedPositionProvider(0.0, 0.5, -10, 0), // left + new BoundsBasedPositionProvider(1.0, 0.5, 10, 0), // right + new BoundsBasedPositionProvider(0.5, 1.0, 0, 10), // bottom + }; + + var providers2 = new IPositionProvider[] + { + new ShapeAnglePositionProvider(45, 10, 10), // bottom right + new ShapeAnglePositionProvider(135, -10, 10), // bottom left + new ShapeAnglePositionProvider(225, -10, -10), // top left + new ShapeAnglePositionProvider(315, 10, -10), // top right + }; + + var link1 = new LinkModel(new DynamicAnchor(node1, providers1), new DynamicAnchor(node2, providers2)) + { + PathGenerator = new SmoothPathGenerator(), + SourceMarker = LinkMarker.Arrow, + TargetMarker = LinkMarker.Arrow + }; + + _blazorDiagram.Nodes.Add(new[] { node1, node2, node3 }); + _blazorDiagram.Links.Add(link1); + var link2 = _blazorDiagram.Links.Add(new LinkModel(new ShapeIntersectionAnchor(node3), new LinkAnchor(link1, 0.5)) + { + PathGenerator = new StraightPathGenerator(), + SourceMarker = LinkMarker.Arrow, + TargetMarker = LinkMarker.Arrow + }); + + _blazorDiagram.Controls.AddFor(node1) + .Add(new RemoveControl(1, 0)) + .Add(new DragNewLinkControl(1, 0.5, 20)) + .Add(new BoundaryControl()); + + _blazorDiagram.Controls.AddFor(node2) + .Add(new RemoveControl(1, 0)) + .Add(new DragNewLinkControl(1, 0.5, 20)) + .Add(new BoundaryControl()); + + _blazorDiagram.Controls.AddFor(link1) + .Add(new RemoveControl(new LinkPathPositionProvider(0.1))) + .Add(new ArrowHeadControl(true, LinkMarker.NewArrow(30, 30))) + .Add(new ArrowHeadControl(false, LinkMarker.NewArrow(30, 30))) + .Add(new BoundaryControl()); + + _blazorDiagram.Controls.AddFor(link2) + .Add(new RemoveControl(new LinkPathPositionProvider(0.8))) + .Add(new ArrowHeadControl(true)) + .Add(new ArrowHeadControl(false)) + .Add(new BoundaryControl()); + + _blazorDiagram.Options.Links.RequireTarget = false; + + _blazorDiagram.Links.Added += OnLinkAdded; + } + + private void OnLinkAdded(Blazor.Diagrams.Core.Models.Base.BaseLinkModel link) + { + _blazorDiagram.Controls.AddFor(link) + .Add(new ArrowHeadControl(true)) + .Add(new ArrowHeadControl(false)); + } + + private static NodeModel NewNode(double x, double y) + { + var node = new NodeModel(new Point(x, y)); + node.AddPort(PortAlignment.Bottom); + node.AddPort(PortAlignment.Top); + node.AddPort(PortAlignment.Left); + node.AddPort(PortAlignment.Right); + return node; + } + +} \ No newline at end of file diff --git a/samples/SharedDemo/Demos/DragAndDrop.razor b/samples/SharedDemo/Demos/DragAndDrop.razor index 0e1dd3776..24b6c340e 100644 --- a/samples/SharedDemo/Demos/DragAndDrop.razor +++ b/samples/SharedDemo/Demos/DragAndDrop.razor @@ -8,20 +8,24 @@
- - Default Node +
+ + Default Node +
- - Bot Answer Node +
+ + Bot Answer Node +
- +
diff --git a/samples/SharedDemo/Demos/DragAndDrop.razor.cs b/samples/SharedDemo/Demos/DragAndDrop.razor.cs index c5be42c4d..0e049b058 100644 --- a/samples/SharedDemo/Demos/DragAndDrop.razor.cs +++ b/samples/SharedDemo/Demos/DragAndDrop.razor.cs @@ -1,42 +1,41 @@ -using Blazor.Diagrams.Core; +using Blazor.Diagrams; using Blazor.Diagrams.Core.Models; using Microsoft.AspNetCore.Components.Web; -namespace SharedDemo.Demos +namespace SharedDemo.Demos; + +public partial class DragAndDrop { - public partial class DragAndDrop + private readonly BlazorDiagram _blazorDiagram = new BlazorDiagram(); + private int? _draggedType; + + protected override void OnInitialized() { - private readonly Diagram _diagram = new Diagram(); - private int? _draggedType; - - protected override void OnInitialized() - { - base.OnInitialized(); - - LayoutData.Title = "Drag & Drop"; - LayoutData.Info = "A very simple drag & drop implementation using the HTML5 events."; - LayoutData.DataChanged(); - - _diagram.RegisterModelComponent(); - } - - private void OnDragStart(int key) - { - // Can also use transferData, but this is probably "faster" - _draggedType = key; - } - - private void OnDrop(DragEventArgs e) - { - if (_draggedType == null) // Unkown item - return; - - var position = _diagram.GetRelativeMousePoint(e.ClientX, e.ClientY); - var node = _draggedType == 0 ? new NodeModel(position) : new BotAnswerNode(position); - node.AddPort(PortAlignment.Top); - node.AddPort(PortAlignment.Bottom); - _diagram.Nodes.Add(node); - _draggedType = null; - } + base.OnInitialized(); + + LayoutData.Title = "Drag & Drop"; + LayoutData.Info = "A very simple drag & drop implementation using the HTML5 events."; + LayoutData.DataChanged(); + + _blazorDiagram.RegisterComponent(); + } + + private void OnDragStart(int key) + { + // Can also use transferData, but this is probably "faster" + _draggedType = key; + } + + private void OnDrop(DragEventArgs e) + { + if (_draggedType == null) // Unkown item + return; + + var position = _blazorDiagram.GetRelativeMousePoint(e.ClientX, e.ClientY); + var node = _draggedType == 0 ? new NodeModel(position) : new BotAnswerNode(position); + node.AddPort(PortAlignment.Top); + node.AddPort(PortAlignment.Bottom); + _blazorDiagram.Nodes.Add(node); + _draggedType = null; } } diff --git a/samples/SharedDemo/Demos/DynamicInsertions.razor b/samples/SharedDemo/Demos/DynamicInsertions.razor index 252882cf2..9992424e8 100644 --- a/samples/SharedDemo/Demos/DynamicInsertions.razor +++ b/samples/SharedDemo/Demos/DynamicInsertions.razor @@ -22,6 +22,6 @@ - + diff --git a/samples/SharedDemo/Demos/DynamicInsertions.razor.cs b/samples/SharedDemo/Demos/DynamicInsertions.razor.cs index 1f6874f4b..7b4cae3f3 100644 --- a/samples/SharedDemo/Demos/DynamicInsertions.razor.cs +++ b/samples/SharedDemo/Demos/DynamicInsertions.razor.cs @@ -1,88 +1,100 @@ -using Blazor.Diagrams.Core; +using Blazor.Diagrams; +using Blazor.Diagrams.Core.Anchors; +using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Core.Models; using Microsoft.AspNetCore.Components; -using Blazor.Diagrams.Core.Geometry; using System; using System.Linq; -namespace SharedDemo.Demos +namespace SharedDemo.Demos; + +public class DynamicInsertionsComponent : ComponentBase { - public class DynamicInsertionsComponent : ComponentBase + private static readonly Random _random = new Random(); + protected readonly BlazorDiagram BlazorDiagram = new BlazorDiagram(); + + protected override void OnInitialized() { - private static readonly Random _random = new Random(); - protected readonly Diagram diagram = new Diagram(); + base.OnInitialized(); - protected override void OnInitialized() + BlazorDiagram.Options.Groups.Enabled = true; + BlazorDiagram.Nodes.Add(new NodeModel(new Point(300, 50))); + BlazorDiagram.Nodes.Add(new NodeModel(new Point(300, 400))); + + BlazorDiagram.Options.Links.Factory = (d, s, ta) => { - base.OnInitialized(); + var link = new LinkModel(new SinglePortAnchor(s as PortModel) + { + UseShapeAndAlignment = false + }, ta) + { + SourceMarker = LinkMarker.Arrow + }; + return link; + }; + } - diagram.Options.Groups.Enabled = true; - diagram.Nodes.Add(new NodeModel(new Point(300, 50))); - diagram.Nodes.Add(new NodeModel(new Point(300, 400))); - } + protected void AddNode() + { + var x = _random.Next(0, (int)BlazorDiagram.Container.Width - 120); + var y = _random.Next(0, (int)BlazorDiagram.Container.Height - 100); + BlazorDiagram.Nodes.Add(new NodeModel(new Point(x, y))); + } - protected void AddNode() - { - var x = _random.Next(0, (int)diagram.Container.Width - 120); - var y = _random.Next(0, (int)diagram.Container.Height - 100); - diagram.Nodes.Add(new NodeModel(new Point(x, y))); - } + protected void RemoveNode() + { + var i = _random.Next(0, BlazorDiagram.Nodes.Count); + BlazorDiagram.Nodes.Remove(BlazorDiagram.Nodes[i]); + } - protected void RemoveNode() - { - var i = _random.Next(0, diagram.Nodes.Count); - diagram.Nodes.Remove(diagram.Nodes[i]); - } + protected void AddPort() + { + var node = BlazorDiagram.Nodes.FirstOrDefault(n => n.Selected); + if (node == null) + return; - protected void AddPort() + foreach (PortAlignment portAlignment in Enum.GetValues(typeof(PortAlignment))) { - var node = diagram.Nodes.FirstOrDefault(n => n.Selected); - if (node == null) - return; - - foreach(PortAlignment portAlignment in Enum.GetValues(typeof(PortAlignment))) + if (node.GetPort(portAlignment) == null) { - if(node.GetPort(portAlignment) == null) - { - node.AddPort(portAlignment); - node.Refresh(); - break; - } - } + node.AddPort(portAlignment); + node.Refresh(); + break; + } } + } - protected void RemovePort() - { - var node = diagram.Nodes.FirstOrDefault(n => n.Selected); - if (node == null) - return; + protected void RemovePort() + { + var node = BlazorDiagram.Nodes.FirstOrDefault(n => n.Selected); + if (node == null) + return; - if (node.Ports.Count == 0) - return; + if (node.Ports.Count == 0) + return; - var i = _random.Next(0, node.Ports.Count); - var port = node.Ports[i]; + var i = _random.Next(0, node.Ports.Count); + var port = node.Ports[i]; - diagram.Links.Remove(port.Links.ToArray()); - node.RemovePort(port); - node.Refresh(); - } + BlazorDiagram.Links.Remove(port.Links.ToArray()); + node.RemovePort(port); + node.Refresh(); + } - protected void AddLink() - { - var selectedNodes = diagram.Nodes.Where(n => n.Selected).ToArray(); - if (selectedNodes.Length != 2) - return; + protected void AddLink() + { + var selectedNodes = BlazorDiagram.Nodes.Where(n => n.Selected).ToArray(); + if (selectedNodes.Length != 2) + return; - var node1 = selectedNodes[0]; - var node2 = selectedNodes[1]; + var node1 = selectedNodes[0]; + var node2 = selectedNodes[1]; - if (node1 == null || node1.Ports.Count == 0 || node2 == null || node2.Ports.Count == 0) - return; + if (node1 == null || node1.Ports.Count == 0 || node2 == null || node2.Ports.Count == 0) + return; - var sourcePort = node1.Ports[_random.Next(0, node1.Ports.Count)]; - var targetPort = node2.Ports[_random.Next(0, node2.Ports.Count)]; - diagram.Links.Add(new LinkModel(sourcePort, targetPort)); - } + var sourcePort = node1.Ports[_random.Next(0, node1.Ports.Count)]; + var targetPort = node2.Ports[_random.Next(0, node2.Ports.Count)]; + BlazorDiagram.Links.Add(new LinkModel(sourcePort, targetPort)); } } diff --git a/samples/SharedDemo/Demos/Events.razor b/samples/SharedDemo/Demos/Events.razor index 938ccd34f..85af8f2e1 100644 --- a/samples/SharedDemo/Demos/Events.razor +++ b/samples/SharedDemo/Demos/Events.razor @@ -16,7 +16,7 @@ }
- +
diff --git a/samples/SharedDemo/Demos/Events.razor.cs b/samples/SharedDemo/Demos/Events.razor.cs index d83cfa26b..f44ed5310 100644 --- a/samples/SharedDemo/Demos/Events.razor.cs +++ b/samples/SharedDemo/Demos/Events.razor.cs @@ -1,94 +1,82 @@ -using Blazor.Diagrams.Core; +using Blazor.Diagrams; using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Core.Models; using Microsoft.AspNetCore.Components; using System.Collections.Generic; -namespace SharedDemo.Demos +namespace SharedDemo.Demos; + +public class EventsComponent : ComponentBase { - public class EventsComponent : ComponentBase - { - protected readonly Diagram diagram = new Diagram(); - protected readonly List events = new List(); + protected readonly BlazorDiagram BlazorDiagram = new BlazorDiagram(); + protected readonly List events = new List(); - protected override void OnInitialized() - { - base.OnInitialized(); + protected override void OnInitialized() + { + base.OnInitialized(); - RegisterEvents(); + RegisterEvents(); - var node1 = NewNode(50, 50); - var node2 = NewNode(300, 300); - diagram.Nodes.Add(new[] { node1, node2, NewNode(300, 50) }); - diagram.Links.Add(new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left))); - } + var node1 = NewNode(50, 50); + var node2 = NewNode(300, 300); + BlazorDiagram.Nodes.Add(new[] { node1, node2, NewNode(300, 50) }); + BlazorDiagram.Links.Add(new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left))); + } - private void RegisterEvents() + private void RegisterEvents() + { + BlazorDiagram.Changed += () => { - diagram.Changed += () => - { - events.Add("Changed"); - StateHasChanged(); - }; - - diagram.Nodes.Added += (n) => events.Add($"NodesAdded, NodeId={n.Id}"); - diagram.Nodes.Removed += (n) => events.Add($"NodesRemoved, NodeId={n.Id}"); - - diagram.SelectionChanged += (m) => - { - events.Add($"SelectionChanged, Id={m.Id}, Type={m.GetType().Name}, Selected={m.Selected}"); - StateHasChanged(); - }; + events.Add("Changed"); + StateHasChanged(); + }; - diagram.Links.Added += (l) => events.Add($"Links.Added, LinkId={l.Id}"); + BlazorDiagram.Nodes.Added += (n) => events.Add($"NodesAdded, NodeId={n.Id}"); + BlazorDiagram.Nodes.Removed += (n) => events.Add($"NodesRemoved, NodeId={n.Id}"); - diagram.Links.Removed += (l) => events.Add($"Links.Removed, LinkId={l.Id}"); - - diagram.MouseDown += (m, e) => - { - events.Add($"MouseDown, Type={m?.GetType().Name}, ModelId={m?.Id}"); - StateHasChanged(); - }; + BlazorDiagram.SelectionChanged += (m) => + { + events.Add($"SelectionChanged, Id={m.Id}, Type={m.GetType().Name}, Selected={m.Selected}"); + StateHasChanged(); + }; - diagram.MouseUp += (m, e) => - { - events.Add($"MouseUp, Type={m?.GetType().Name}, ModelId={m?.Id}"); - StateHasChanged(); - }; + BlazorDiagram.Links.Added += (l) => events.Add($"Links.Added, LinkId={l.Id}"); - diagram.TouchStart += (m, e) => - { - events.Add($"TouchStart, Type={m?.GetType().Name}, ModelId={m?.Id}"); - StateHasChanged(); - }; + BlazorDiagram.Links.Removed += (l) => events.Add($"Links.Removed, LinkId={l.Id}"); - diagram.TouchEnd += (m, e) => - { - events.Add($"TouchEnd, Type={m?.GetType().Name}, ModelId={m?.Id}"); - StateHasChanged(); - }; + BlazorDiagram.PointerDown += (m, e) => + { + events.Add($"MouseDown, Type={m?.GetType().Name}, ModelId={m?.Id}"); + StateHasChanged(); + }; - diagram.MouseClick += (m, e) => - { - events.Add($"MouseClick, Type={m?.GetType().Name}, ModelId={m?.Id}"); - StateHasChanged(); - }; + BlazorDiagram.PointerUp += (m, e) => + { + events.Add($"MouseUp, Type={m?.GetType().Name}, ModelId={m?.Id}"); + StateHasChanged(); + }; - diagram.MouseDoubleClick += (m, e) => - { - events.Add($"MouseDoubleClick, Type={m?.GetType().Name}, ModelId={m?.Id}"); - StateHasChanged(); - }; - } + BlazorDiagram.PointerClick += (m, e) => + { + events.Add($"MouseClick, Type={m?.GetType().Name}, ModelId={m?.Id}"); + StateHasChanged(); + }; - private NodeModel NewNode(double x, double y) + BlazorDiagram.PointerDoubleClick += (m, e) => { - var node = new NodeModel(new Point(x, y)); - node.AddPort(PortAlignment.Bottom); - node.AddPort(PortAlignment.Top); - node.AddPort(PortAlignment.Left); - node.AddPort(PortAlignment.Right); - return node; - } + events.Add($"MouseDoubleClick, Type={m?.GetType().Name}, ModelId={m?.Id}"); + StateHasChanged(); + }; + } + + private NodeModel NewNode(double x, double y) + { + var node = new NodeModel(new Point(x, y)); + node.AddPort(PortAlignment.Bottom); + node.AddPort(PortAlignment.Top); + node.AddPort(PortAlignment.Left); + node.AddPort(PortAlignment.Right); + node.Moved += (m) => events.Add($"Node.Moved, NodeId={node.Id}"); + return node; } } diff --git a/samples/SharedDemo/Demos/Groups/CustomShortcut.razor b/samples/SharedDemo/Demos/Groups/CustomShortcut.razor index c4856196f..dac358855 100644 --- a/samples/SharedDemo/Demos/Groups/CustomShortcut.razor +++ b/samples/SharedDemo/Demos/Groups/CustomShortcut.razor @@ -2,10 +2,11 @@ @layout DemoLayout @inject LayoutData LayoutData - + - + diff --git a/samples/SharedDemo/Demos/Groups/CustomShortcut.razor.cs b/samples/SharedDemo/Demos/Groups/CustomShortcut.razor.cs index c988ed75e..cfb0dbfeb 100644 --- a/samples/SharedDemo/Demos/Groups/CustomShortcut.razor.cs +++ b/samples/SharedDemo/Demos/Groups/CustomShortcut.razor.cs @@ -1,40 +1,44 @@ -using Blazor.Diagrams.Core; -using Blazor.Diagrams.Core.Models; +using Blazor.Diagrams; +using Blazor.Diagrams.Core.Behaviors; using Blazor.Diagrams.Core.Geometry; +using Blazor.Diagrams.Core.Models; + +namespace SharedDemo.Demos.Groups; -namespace SharedDemo.Demos.Groups +public partial class CustomShortcut { - public partial class CustomShortcut + private BlazorDiagram _blazorDiagram = new BlazorDiagram(); + + protected override void OnInitialized() + { + base.OnInitialized(); + + LayoutData.Title = "Custom Shortcut"; + LayoutData.Info = "You can customize what needs to be pressed to group selected nodes. Ctrl+Shift+k in this example."; + LayoutData.DataChanged(); + + _blazorDiagram.Options.Groups.Enabled = true; + _blazorDiagram.Options.LinksLayerOrder = 2; + _blazorDiagram.Options.NodesLayerOrder = 1; + var ksb = _blazorDiagram.GetBehavior(); + ksb.RemoveShortcut("g", true, false, true); + ksb.SetShortcut("k", true, true, false, KeyboardShortcutsDefaults.Grouping); + + var node1 = NewNode(50, 50); + var node2 = NewNode(250, 250); + var node3 = NewNode(500, 100); + _blazorDiagram.Nodes.Add(new[] { node1, node2, node3 }); + + _blazorDiagram.Links.Add(new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left))); + } + + private NodeModel NewNode(double x, double y) { - private Diagram _diagram = new Diagram(); - - protected override void OnInitialized() - { - base.OnInitialized(); - - LayoutData.Title = "Custom Shortcut"; - LayoutData.Info = "You can customize what needs to be pressed to group selected nodes. CTRL+SHIFT+K in this example."; - LayoutData.DataChanged(); - - _diagram.Options.Groups.Enabled = true; - _diagram.Options.Groups.KeyboardShortcut = e => e.CtrlKey && e.ShiftKey && e.Key.ToLower() == "k"; - - var node1 = NewNode(50, 50); - var node2 = NewNode(250, 250); - var node3 = NewNode(500, 100); - _diagram.Nodes.Add(new[] { node1, node2, node3 }); - - _diagram.Links.Add(new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left))); - } - - private NodeModel NewNode(double x, double y) - { - var node = new NodeModel(new Point(x, y)); - node.AddPort(PortAlignment.Bottom); - node.AddPort(PortAlignment.Top); - node.AddPort(PortAlignment.Left); - node.AddPort(PortAlignment.Right); - return node; - } + var node = new NodeModel(new Point(x, y)); + node.AddPort(PortAlignment.Bottom); + node.AddPort(PortAlignment.Top); + node.AddPort(PortAlignment.Left); + node.AddPort(PortAlignment.Right); + return node; } } diff --git a/samples/SharedDemo/Demos/Groups/Dynamic.razor b/samples/SharedDemo/Demos/Groups/Dynamic.razor index d5ac1f9cc..0defe27b2 100644 --- a/samples/SharedDemo/Demos/Groups/Dynamic.razor +++ b/samples/SharedDemo/Demos/Groups/Dynamic.razor @@ -8,10 +8,11 @@ - + - + diff --git a/samples/SharedDemo/Demos/Groups/Dynamic.razor.cs b/samples/SharedDemo/Demos/Groups/Dynamic.razor.cs index 25bfbb0cf..fa64b8e10 100644 --- a/samples/SharedDemo/Demos/Groups/Dynamic.razor.cs +++ b/samples/SharedDemo/Demos/Groups/Dynamic.razor.cs @@ -1,74 +1,76 @@ -using Blazor.Diagrams.Core; -using Blazor.Diagrams.Core.Models; +using Blazor.Diagrams; using Blazor.Diagrams.Core.Geometry; +using Blazor.Diagrams.Core.Models; using System; -namespace SharedDemo.Demos.Groups +namespace SharedDemo.Demos.Groups; + +public partial class Dynamic { - public partial class Dynamic - { - private readonly Diagram _diagram = new Diagram(); + private readonly BlazorDiagram _blazorDiagram = new BlazorDiagram(); - protected override void OnInitialized() - { - base.OnInitialized(); + protected override void OnInitialized() + { + base.OnInitialized(); - LayoutData.Title = "Dynamic Groups"; - LayoutData.Info = "You can create and modify groups dynamically!"; - LayoutData.DataChanged(); + LayoutData.Title = "Dynamic Groups"; + LayoutData.Info = "You can create and modify groups dynamically!"; + LayoutData.DataChanged(); + + _blazorDiagram.Options.LinksLayerOrder = 2; + _blazorDiagram.Options.NodesLayerOrder = 1; - var node1 = NewNode(50, 150); - var node2 = NewNode(250, 350); - var node3 = NewNode(500, 200); - _diagram.Nodes.Add(new[] { node1, node2, node3 }); - _diagram.Links.Add(new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left))); - } + var node1 = NewNode(50, 150); + var node2 = NewNode(250, 350); + var node3 = NewNode(500, 200); + _blazorDiagram.Nodes.Add(new[] { node1, node2, node3 }); + _blazorDiagram.Links.Add(new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left))); + } - private void AddEmptyGroup() + private void AddEmptyGroup() + { + _blazorDiagram.Groups.Add(new GroupModel(Array.Empty()) { - _diagram.AddGroup(new GroupModel(Array.Empty()) - { - Position = new Point(100, 100) - }); - } + Position = new Point(100, 100) + }); + } - private void AddChildToGroup() - { - if (_diagram.Groups.Count == 0) - return; + private void AddChildToGroup() + { + if (_blazorDiagram.Groups.Count == 0) + return; - foreach (var node in _diagram.Nodes) + foreach (var node in _blazorDiagram.Nodes) + { + if (node.Group == null) { - if (node.Group == null) - { - _diagram.Groups[0].AddChild(node); - _diagram.Refresh(); - return; - } + _blazorDiagram.Groups[0].AddChild(node); + _blazorDiagram.Refresh(); + return; } } + } - private void RemoveChildFromGroup() + private void RemoveChildFromGroup() + { + foreach (var node in _blazorDiagram.Nodes) { - foreach (var node in _diagram.Nodes) + if (node.Group != null) { - if (node.Group != null) - { - node.Group.RemoveChild(node); - _diagram.Refresh(); - return; - } + node.Group.RemoveChild(node); + _blazorDiagram.Refresh(); + return; } } + } - private NodeModel NewNode(double x, double y) - { - var node = new NodeModel(new Point(x, y)); - node.AddPort(PortAlignment.Bottom); - node.AddPort(PortAlignment.Top); - node.AddPort(PortAlignment.Left); - node.AddPort(PortAlignment.Right); - return node; - } + private NodeModel NewNode(double x, double y) + { + var node = new NodeModel(new Point(x, y)); + node.AddPort(PortAlignment.Bottom); + node.AddPort(PortAlignment.Top); + node.AddPort(PortAlignment.Left); + node.AddPort(PortAlignment.Right); + return node; } } diff --git a/samples/SharedDemo/Demos/Groups/Factory.razor b/samples/SharedDemo/Demos/Groups/Factory.razor index 1283913c4..37973fd2d 100644 --- a/samples/SharedDemo/Demos/Groups/Factory.razor +++ b/samples/SharedDemo/Demos/Groups/Factory.razor @@ -2,10 +2,11 @@ @layout DemoLayout @inject LayoutData LayoutData - + - + diff --git a/samples/SharedDemo/Demos/Groups/Factory.razor.cs b/samples/SharedDemo/Demos/Groups/Factory.razor.cs index 289e9fbb0..ac008eadc 100644 --- a/samples/SharedDemo/Demos/Groups/Factory.razor.cs +++ b/samples/SharedDemo/Demos/Groups/Factory.razor.cs @@ -1,49 +1,50 @@ -using Blazor.Diagrams.Core; -using Blazor.Diagrams.Core.Models; +using Blazor.Diagrams; using Blazor.Diagrams.Core.Geometry; +using Blazor.Diagrams.Core.Models; + +namespace SharedDemo.Demos.Groups; -namespace SharedDemo.Demos.Groups +public partial class Factory { - public partial class Factory + protected readonly BlazorDiagram BlazorDiagram = new BlazorDiagram(); + + protected override void OnInitialized() { - protected readonly Diagram diagram = new Diagram(); + base.OnInitialized(); - protected override void OnInitialized() - { - base.OnInitialized(); - - LayoutData.Title = "Groups Factory"; - LayoutData.Info = "Factory setting is a way to customize how groups (models) are created when the user uses the shortcut. " + - "Try to group nodes using CTRL+ALT+G now."; - LayoutData.DataChanged(); - - diagram.Options.Groups.Enabled = true; - diagram.Options.Groups.Factory = (diagram, children) => - { - var group = new GroupModel(children, 25); - group.AddPort(PortAlignment.Top); - group.AddPort(PortAlignment.Bottom); - group.AddPort(PortAlignment.Right); - group.AddPort(PortAlignment.Left); - return group; - }; - - var node1 = NewNode(50, 50); - var node2 = NewNode(250, 250); - var node3 = NewNode(500, 100); - diagram.Nodes.Add(new[] { node1, node2, node3 }); - - diagram.Links.Add(new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left))); - } - - private NodeModel NewNode(double x, double y) + LayoutData.Title = "Groups Factory"; + LayoutData.Info = "Factory setting is a way to customize how groups (models) are created when the user uses the shortcut. " + + "Try to group nodes using CTRL+ALT+G now."; + LayoutData.DataChanged(); + + BlazorDiagram.Options.Groups.Enabled = true; + BlazorDiagram.Options.LinksLayerOrder = 2; + BlazorDiagram.Options.NodesLayerOrder = 1; + BlazorDiagram.Options.Groups.Factory = (diagram, children) => { - var node = new NodeModel(new Point(x, y)); - node.AddPort(PortAlignment.Bottom); - node.AddPort(PortAlignment.Top); - node.AddPort(PortAlignment.Left); - node.AddPort(PortAlignment.Right); - return node; - } + var group = new GroupModel(children, 25); + group.AddPort(PortAlignment.Top); + group.AddPort(PortAlignment.Bottom); + group.AddPort(PortAlignment.Right); + group.AddPort(PortAlignment.Left); + return group; + }; + + var node1 = NewNode(50, 50); + var node2 = NewNode(250, 250); + var node3 = NewNode(500, 100); + BlazorDiagram.Nodes.Add(new[] { node1, node2, node3 }); + + BlazorDiagram.Links.Add(new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left))); + } + + private NodeModel NewNode(double x, double y) + { + var node = new NodeModel(new Point(x, y)); + node.AddPort(PortAlignment.Bottom); + node.AddPort(PortAlignment.Top); + node.AddPort(PortAlignment.Left); + node.AddPort(PortAlignment.Right); + return node; } } diff --git a/samples/SharedDemo/Demos/Groups/Grouping.razor b/samples/SharedDemo/Demos/Groups/Grouping.razor index ee82cd1ad..9ba1eded5 100644 --- a/samples/SharedDemo/Demos/Groups/Grouping.razor +++ b/samples/SharedDemo/Demos/Groups/Grouping.razor @@ -15,10 +15,13 @@ } } - + - + + diff --git a/samples/SharedDemo/Demos/Groups/Grouping.razor.cs b/samples/SharedDemo/Demos/Groups/Grouping.razor.cs index 0f9b57828..dd87f311e 100644 --- a/samples/SharedDemo/Demos/Groups/Grouping.razor.cs +++ b/samples/SharedDemo/Demos/Groups/Grouping.razor.cs @@ -1,35 +1,46 @@ -using Blazor.Diagrams.Core; +using Blazor.Diagrams; +using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Core.Models; using Microsoft.AspNetCore.Components; -using Blazor.Diagrams.Core.Geometry; -namespace SharedDemo.Demos +namespace SharedDemo.Demos; + +public class GroupingComponent : ComponentBase { - public class GroupingComponent : ComponentBase + protected readonly BlazorDiagram BlazorDiagram = new BlazorDiagram(); + + protected override void OnInitialized() + { + base.OnInitialized(); + + BlazorDiagram.Options.Groups.Enabled = true; + BlazorDiagram.Options.LinksLayerOrder = 2; + BlazorDiagram.Options.NodesLayerOrder = 1; + var node1 = NewNode(50, 50); + var node2 = NewNode(250, 250); + var node3 = NewNode(500, 100); + var node4 = NewNode(700, 350); + BlazorDiagram.Nodes.Add(new[] { node1, node2, node3 }); + + BlazorDiagram.Links.Add(new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left))); + BlazorDiagram.Links.Add(new LinkModel(node2.GetPort(PortAlignment.Right), node3.GetPort(PortAlignment.Left))); + BlazorDiagram.Links.Add(new LinkModel(node1.GetPort(PortAlignment.Right), node3.GetPort(PortAlignment.Left))); + + var group1 = BlazorDiagram.Groups.Group(node1, node2); + var group2 = BlazorDiagram.Groups.Group(group1, node3); + + BlazorDiagram.Nodes.Add(node4); + + BlazorDiagram.Links.Add(new LinkModel(group2, node4)); + } + + private NodeModel NewNode(double x, double y) { - protected readonly Diagram diagram = new Diagram(); - - protected override void OnInitialized() - { - base.OnInitialized(); - - diagram.Options.Groups.Enabled = true; - var node1 = NewNode(50, 50); - var node2 = NewNode(250, 250); - var node3 = NewNode(500, 100); - diagram.Nodes.Add(new[] { node1, node2, node3 }); - - diagram.Links.Add(new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left))); - } - - private NodeModel NewNode(double x, double y) - { - var node = new NodeModel(new Point(x, y)); - node.AddPort(PortAlignment.Bottom); - node.AddPort(PortAlignment.Top); - node.AddPort(PortAlignment.Left); - node.AddPort(PortAlignment.Right); - return node; - } + var node = new NodeModel(new Point(x, y)); + node.AddPort(PortAlignment.Bottom); + node.AddPort(PortAlignment.Top); + node.AddPort(PortAlignment.Left); + node.AddPort(PortAlignment.Right); + return node; } } diff --git a/samples/SharedDemo/Demos/Links/LabelsDemo.razor b/samples/SharedDemo/Demos/Links/LabelsDemo.razor index fd8929975..e4552a081 100644 --- a/samples/SharedDemo/Demos/Links/LabelsDemo.razor +++ b/samples/SharedDemo/Demos/Links/LabelsDemo.razor @@ -2,6 +2,6 @@ @layout DemoLayout @inject LayoutData LayoutData - + \ No newline at end of file diff --git a/samples/SharedDemo/Demos/Links/LabelsDemo.razor.cs b/samples/SharedDemo/Demos/Links/LabelsDemo.razor.cs index b824fc5e5..a882016a2 100644 --- a/samples/SharedDemo/Demos/Links/LabelsDemo.razor.cs +++ b/samples/SharedDemo/Demos/Links/LabelsDemo.razor.cs @@ -1,79 +1,74 @@ -using Blazor.Diagrams.Core; +using Blazor.Diagrams; using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Core.Models; -using Blazor.Diagrams.Core.Models.Base; -using System; -using System.Collections.Generic; -using System.Text; -namespace SharedDemo.Demos.Links +namespace SharedDemo.Demos.Links; + +public partial class LabelsDemo { - public partial class LabelsDemo - { - private Diagram _diagram = new Diagram(); + private BlazorDiagram _blazorDiagram = new BlazorDiagram(); - protected override void OnInitialized() - { - base.OnInitialized(); + protected override void OnInitialized() + { + base.OnInitialized(); - LayoutData.Title = "Link Labels"; - LayoutData.Info = "Labels help you show more information through out a link. You can specify a distance or an offset.
" + - "The content of the labels is still limited because of Blazor's poor SVG support."; - LayoutData.DataChanged(); + LayoutData.Title = "Link Labels"; + LayoutData.Info = "Labels help you show more information through out a link. You can specify a distance or an offset.
" + + "The content of the labels is still limited because of Blazor's poor SVG support."; + LayoutData.DataChanged(); - InitializeDiagram(); - } + InitializeDiagram(); + } - private void InitializeDiagram() - { - var node1 = NewNode(50, 50); - var node2 = NewNode(400, 50); + private void InitializeDiagram() + { + var node1 = NewNode(50, 50); + var node2 = NewNode(400, 50); - _diagram.Nodes.Add(new[] { node1, node2 }); + _blazorDiagram.Nodes.Add(new[] { node1, node2 }); - var link = new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)); - link.Labels.Add(new LinkLabelModel(link, "Content")); - _diagram.Links.Add(link); + var link = new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)); + link.Labels.Add(new LinkLabelModel(link, "Content")); + _blazorDiagram.Links.Add(link); - node1 = NewNode(50, 160); - node2 = NewNode(400, 160); + node1 = NewNode(50, 160); + node2 = NewNode(400, 160); - _diagram.Nodes.Add(new[] { node1, node2 }); + _blazorDiagram.Nodes.Add(new[] { node1, node2 }); - link = new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)); - link.Labels.Add(new LinkLabelModel(link, "0.25", 0.3)); - link.Labels.Add(new LinkLabelModel(link, "0.75", 0.7)); - _diagram.Links.Add(link); + link = new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)); + link.Labels.Add(new LinkLabelModel(link, "0.25", 0.3)); + link.Labels.Add(new LinkLabelModel(link, "0.75", 0.7)); + _blazorDiagram.Links.Add(link); - node1 = NewNode(50, 270); - node2 = NewNode(400, 270); + node1 = NewNode(50, 270); + node2 = NewNode(400, 270); - _diagram.Nodes.Add(new[] { node1, node2 }); + _blazorDiagram.Nodes.Add(new[] { node1, node2 }); - link = new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)); - link.Labels.Add(new LinkLabelModel(link, "50", 50)); - link.Labels.Add(new LinkLabelModel(link, "-50", -50)); - _diagram.Links.Add(link); + link = new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)); + link.Labels.Add(new LinkLabelModel(link, "50", 50)); + link.Labels.Add(new LinkLabelModel(link, "-50", -50)); + _blazorDiagram.Links.Add(link); - node1 = NewNode(50, 380); - node2 = NewNode(400, 380); + node1 = NewNode(50, 380); + node2 = NewNode(400, 380); - _diagram.Nodes.Add(new[] { node1, node2 }); + _blazorDiagram.Nodes.Add(new[] { node1, node2 }); - link = new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)); - link.Labels.Add(new LinkLabelModel(link, "(0,-20)", 50, new Point(0, -20))); - link.Labels.Add(new LinkLabelModel(link, "(0,20)", -50, new Point(0, 20))); - _diagram.Links.Add(link); - } + link = new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)); + link.Labels.Add(new LinkLabelModel(link, "(0,-20)", 50, new Point(0, -20))); + link.Labels.Add(new LinkLabelModel(link, "(0,20)", -50, new Point(0, 20))); + _blazorDiagram.Links.Add(link); + } - private NodeModel NewNode(double x, double y) - { - var node = new NodeModel(new Point(x, y)); - node.AddPort(PortAlignment.Bottom); - node.AddPort(PortAlignment.Top); - node.AddPort(PortAlignment.Left); - node.AddPort(PortAlignment.Right); - return node; - } + private NodeModel NewNode(double x, double y) + { + var node = new NodeModel(new Point(x, y)); + node.AddPort(PortAlignment.Bottom); + node.AddPort(PortAlignment.Top); + node.AddPort(PortAlignment.Left); + node.AddPort(PortAlignment.Right); + return node; } } diff --git a/samples/SharedDemo/Demos/Links/MarkersDemo.razor b/samples/SharedDemo/Demos/Links/MarkersDemo.razor index 37e4b9431..f5bdd37ca 100644 --- a/samples/SharedDemo/Demos/Links/MarkersDemo.razor +++ b/samples/SharedDemo/Demos/Links/MarkersDemo.razor @@ -2,6 +2,6 @@ @layout DemoLayout @inject LayoutData LayoutData - + \ No newline at end of file diff --git a/samples/SharedDemo/Demos/Links/MarkersDemo.razor.cs b/samples/SharedDemo/Demos/Links/MarkersDemo.razor.cs index 2de943cdd..d0036050c 100644 --- a/samples/SharedDemo/Demos/Links/MarkersDemo.razor.cs +++ b/samples/SharedDemo/Demos/Links/MarkersDemo.razor.cs @@ -1,90 +1,89 @@ -using Blazor.Diagrams.Core; +using Blazor.Diagrams; using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Core.Models; -namespace SharedDemo.Demos.Links +namespace SharedDemo.Demos.Links; + +public partial class MarkersDemo { - public partial class MarkersDemo + private BlazorDiagram _blazorDiagram = new BlazorDiagram(); + + protected override void OnInitialized() + { + base.OnInitialized(); + + LayoutData.Title = "Link Markers"; + LayoutData.Info = "Markers are SVG Paths that you can put at the beginning or at the end of your links."; + LayoutData.DataChanged(); + + InitializeDiagram(); + } + + private void InitializeDiagram() + { + var node1 = NewNode(50, 50); + var node2 = NewNode(400, 50); + + _blazorDiagram.Nodes.Add(new[] { node1, node2 }); + + var link = new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)); + link.SourceMarker = LinkMarker.Arrow; + link.TargetMarker = LinkMarker.Arrow; + link.Labels.Add(new LinkLabelModel(link, "Arrow")); + _blazorDiagram.Links.Add(link); + + node1 = NewNode(50, 160); + node2 = NewNode(400, 160); + + _blazorDiagram.Nodes.Add(new[] { node1, node2 }); + + link = new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)); + link.SourceMarker = LinkMarker.Circle; + link.TargetMarker = LinkMarker.Circle; + link.Labels.Add(new LinkLabelModel(link, "Circle")); + _blazorDiagram.Links.Add(link); + + node1 = NewNode(50, 270); + node2 = NewNode(400, 270); + + _blazorDiagram.Nodes.Add(new[] { node1, node2 }); + + link = new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)); + link.SourceMarker = LinkMarker.Square; + link.TargetMarker = LinkMarker.Square; + link.Labels.Add(new LinkLabelModel(link, "Square")); + _blazorDiagram.Links.Add(link); + + node1 = NewNode(50, 380); + node2 = NewNode(400, 380); + + _blazorDiagram.Nodes.Add(new[] { node1, node2 }); + + link = new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)); + link.SourceMarker = LinkMarker.NewRectangle(10, 20); + link.TargetMarker = LinkMarker.NewArrow(20, 10); + link.Labels.Add(new LinkLabelModel(link, "Factory")); + _blazorDiagram.Links.Add(link); + + node1 = NewNode(50, 490); + node2 = NewNode(400, 490); + + _blazorDiagram.Nodes.Add(new[] { node1, node2 }); + + link = new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)); + link.SourceMarker = new LinkMarker("M 0 -8 L 3 -8 3 8 0 8 z M 4 -8 7 -8 7 8 4 8 z M 8 -8 16 0 8 8 z", 16); + link.TargetMarker = new LinkMarker("M 0 -8 L 8 -8 4 0 8 8 0 8 4 0 z", 8); + link.Labels.Add(new LinkLabelModel(link, "Custom")); + _blazorDiagram.Links.Add(link); + } + + private NodeModel NewNode(double x, double y) { - private Diagram _diagram = new Diagram(); - - protected override void OnInitialized() - { - base.OnInitialized(); - - LayoutData.Title = "Link Markers"; - LayoutData.Info = "Markers are SVG Paths that you can put at the beginning or at the end of your links."; - LayoutData.DataChanged(); - - InitializeDiagram(); - } - - private void InitializeDiagram() - { - var node1 = NewNode(50, 50); - var node2 = NewNode(400, 50); - - _diagram.Nodes.Add(new[] { node1, node2 }); - - var link = new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)); - link.SourceMarker = LinkMarker.Arrow; - link.TargetMarker = LinkMarker.Arrow; - link.Labels.Add(new LinkLabelModel(link, "Arrow")); - _diagram.Links.Add(link); - - node1 = NewNode(50, 160); - node2 = NewNode(400, 160); - - _diagram.Nodes.Add(new[] { node1, node2 }); - - link = new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)); - link.SourceMarker = LinkMarker.Circle; - link.TargetMarker = LinkMarker.Circle; - link.Labels.Add(new LinkLabelModel(link, "Circle")); - _diagram.Links.Add(link); - - node1 = NewNode(50, 270); - node2 = NewNode(400, 270); - - _diagram.Nodes.Add(new[] { node1, node2 }); - - link = new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)); - link.SourceMarker = LinkMarker.Square; - link.TargetMarker = LinkMarker.Square; - link.Labels.Add(new LinkLabelModel(link, "Square")); - _diagram.Links.Add(link); - - node1 = NewNode(50, 380); - node2 = NewNode(400, 380); - - _diagram.Nodes.Add(new[] { node1, node2 }); - - link = new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)); - link.SourceMarker = LinkMarker.NewRectangle(10, 20); - link.TargetMarker = LinkMarker.NewArrow(20, 10); - link.Labels.Add(new LinkLabelModel(link, "Factory")); - _diagram.Links.Add(link); - - node1 = NewNode(50, 490); - node2 = NewNode(400, 490); - - _diagram.Nodes.Add(new[] { node1, node2 }); - - link = new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)); - link.SourceMarker = new LinkMarker("M 0 -8 L 3 -8 3 8 0 8 z M 4 -8 7 -8 7 8 4 8 z M 8 -8 16 0 8 8 z", 16); - link.TargetMarker = new LinkMarker("M 0 -8 L 8 -8 4 0 8 8 0 8 4 0 z", 8); - link.Labels.Add(new LinkLabelModel(link, "Custom")); - _diagram.Links.Add(link); - } - - private NodeModel NewNode(double x, double y) - { - var node = new NodeModel(new Point(x, y)); - node.AddPort(PortAlignment.Bottom); - node.AddPort(PortAlignment.Top); - node.AddPort(PortAlignment.Left); - node.AddPort(PortAlignment.Right); - return node; - } + var node = new NodeModel(new Point(x, y)); + node.AddPort(PortAlignment.Bottom); + node.AddPort(PortAlignment.Top); + node.AddPort(PortAlignment.Left); + node.AddPort(PortAlignment.Right); + return node; } } diff --git a/samples/SharedDemo/Demos/Links/PathGeneratorsDemo.razor b/samples/SharedDemo/Demos/Links/PathGeneratorsDemo.razor index 9b0e08c86..c268430bd 100644 --- a/samples/SharedDemo/Demos/Links/PathGeneratorsDemo.razor +++ b/samples/SharedDemo/Demos/Links/PathGeneratorsDemo.razor @@ -2,6 +2,6 @@ @layout DemoLayout @inject LayoutData LayoutData - + \ No newline at end of file diff --git a/samples/SharedDemo/Demos/Links/PathGeneratorsDemo.razor.cs b/samples/SharedDemo/Demos/Links/PathGeneratorsDemo.razor.cs index 1e56a2b68..55df9b899 100644 --- a/samples/SharedDemo/Demos/Links/PathGeneratorsDemo.razor.cs +++ b/samples/SharedDemo/Demos/Links/PathGeneratorsDemo.razor.cs @@ -1,58 +1,59 @@ -using Blazor.Diagrams.Core; +using Blazor.Diagrams; using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Core.Models; +using Blazor.Diagrams.Core.PathGenerators; +using Blazor.Diagrams.Core.Routers; -namespace SharedDemo.Demos.Links +namespace SharedDemo.Demos.Links; + +public partial class PathGeneratorsDemo { - public partial class PathGeneratorsDemo + private BlazorDiagram _blazorDiagram = new BlazorDiagram(); + + protected override void OnInitialized() { - private Diagram _diagram = new Diagram(); + base.OnInitialized(); - protected override void OnInitialized() - { - base.OnInitialized(); + LayoutData.Title = "Link Path Generators"; + LayoutData.Info = "Path generators are functions that take as input the calculated route and output SVG paths, " + + "alongside the markers positions and their angles. There are currently two generators: Straight and Smooth."; + LayoutData.DataChanged(); - LayoutData.Title = "Link Path Generators"; - LayoutData.Info = "Path generators are functions that take as input the calculated route and output SVG paths, " + - "alongside the markers positions and their angles. There are currently two generators: Straight and Smooth."; - LayoutData.DataChanged(); + InitializeDiagram(); + } + + private void InitializeDiagram() + { + var node1 = NewNode(50, 80); + var node2 = NewNode(300, 350); + var node3 = NewNode(400, 100); - InitializeDiagram(); - } + _blazorDiagram.Nodes.Add(new[] { node1, node2, node3 }); - private void InitializeDiagram() + var link1 = new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)) { - var node1 = NewNode(50, 80); - var node2 = NewNode(300, 350); - var node3 = NewNode(400, 100); - - _diagram.Nodes.Add(new[] { node1, node2, node3 }); - - var link1 = new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)) - { - Router = Routers.Normal, - PathGenerator = PathGenerators.Straight - }; - link1.Labels.Add(new LinkLabelModel(link1, "Straight")); - - var link2 = new LinkModel(node2.GetPort(PortAlignment.Right), node3.GetPort(PortAlignment.Left)) - { - Router = Routers.Normal, - PathGenerator = PathGenerators.Smooth - }; - link2.Labels.Add(new LinkLabelModel(link2, "Smooth")); - - _diagram.Links.Add(new[] { link1, link2 }); - } - - private NodeModel NewNode(double x, double y) + Router = new NormalRouter(), + PathGenerator = new StraightPathGenerator() + }; + link1.Labels.Add(new LinkLabelModel(link1, "Straight")); + + var link2 = new LinkModel(node2.GetPort(PortAlignment.Right), node3.GetPort(PortAlignment.Left)) { - var node = new NodeModel(new Point(x, y)); - node.AddPort(PortAlignment.Bottom); - node.AddPort(PortAlignment.Top); - node.AddPort(PortAlignment.Left); - node.AddPort(PortAlignment.Right); - return node; - } + Router = new NormalRouter(), + PathGenerator = new SmoothPathGenerator() + }; + link2.Labels.Add(new LinkLabelModel(link2, "Smooth")); + + _blazorDiagram.Links.Add(new[] { link1, link2 }); + } + + private NodeModel NewNode(double x, double y) + { + var node = new NodeModel(new Point(x, y)); + node.AddPort(PortAlignment.Bottom); + node.AddPort(PortAlignment.Top); + node.AddPort(PortAlignment.Left); + node.AddPort(PortAlignment.Right); + return node; } } diff --git a/samples/SharedDemo/Demos/Links/RoutersDemo.razor b/samples/SharedDemo/Demos/Links/RoutersDemo.razor index c64a33dc4..cf8d6c6c0 100644 --- a/samples/SharedDemo/Demos/Links/RoutersDemo.razor +++ b/samples/SharedDemo/Demos/Links/RoutersDemo.razor @@ -2,6 +2,6 @@ @layout DemoLayout @inject LayoutData LayoutData - + \ No newline at end of file diff --git a/samples/SharedDemo/Demos/Links/RoutersDemo.razor.cs b/samples/SharedDemo/Demos/Links/RoutersDemo.razor.cs index 8700d4983..c96651a06 100644 --- a/samples/SharedDemo/Demos/Links/RoutersDemo.razor.cs +++ b/samples/SharedDemo/Demos/Links/RoutersDemo.razor.cs @@ -1,57 +1,58 @@ -using Blazor.Diagrams.Core; +using Blazor.Diagrams; using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Core.Models; +using Blazor.Diagrams.Core.PathGenerators; +using Blazor.Diagrams.Core.Routers; -namespace SharedDemo.Demos.Links +namespace SharedDemo.Demos.Links; + +public partial class RoutersDemo { - public partial class RoutersDemo - { - private Diagram _diagram = new Diagram(); + private BlazorDiagram _blazorDiagram = new BlazorDiagram(); - protected override void OnInitialized() - { - base.OnInitialized(); + protected override void OnInitialized() + { + base.OnInitialized(); - LayoutData.Title = "Link Routers"; - LayoutData.Info = "Routers are functions that take as input the link's vertices and can add points in between. " + - "There are currently two routers: Normal and Orthogonal."; - LayoutData.DataChanged(); + LayoutData.Title = "Link Routers"; + LayoutData.Info = "Routers are functions that take as input the link's vertices and can add points in between. " + + "There are currently two routers: Normal and Orthogonal."; + LayoutData.DataChanged(); - InitializeDiagram(); - } + InitializeDiagram(); + } - private void InitializeDiagram() - { - var node1 = NewNode(50, 80); - var node2 = NewNode(300, 350); - var node3 = NewNode(400, 100); + private void InitializeDiagram() + { + var node1 = NewNode(50, 80); + var node2 = NewNode(300, 350); + var node3 = NewNode(400, 100); - _diagram.Nodes.Add(new[] { node1, node2, node3 }); + _blazorDiagram.Nodes.Add(new[] { node1, node2, node3 }); - var link1 = new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)) - { - Router = Routers.Normal - }; - link1.Labels.Add(new LinkLabelModel(link1, "Normal")); + var link1 = new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)) + { + Router = new NormalRouter() + }; + link1.Labels.Add(new LinkLabelModel(link1, "Normal")); - var link2 = new LinkModel(node2.GetPort(PortAlignment.Right), node3.GetPort(PortAlignment.Left)) - { - Router = Routers.Orthogonal, - PathGenerator = PathGenerators.Straight // Smooth results in weird looking links - }; - link2.Labels.Add(new LinkLabelModel(link2, "Orthogonal")); + var link2 = new LinkModel(node2.GetPort(PortAlignment.Right), node3.GetPort(PortAlignment.Left)) + { + Router = new OrthogonalRouter(), + PathGenerator = new StraightPathGenerator() // Smooth results in weird looking links + }; + link2.Labels.Add(new LinkLabelModel(link2, "Orthogonal")); - _diagram.Links.Add(new[] { link1, link2 }); - } + _blazorDiagram.Links.Add(new[] { link1, link2 }); + } - private NodeModel NewNode(double x, double y) - { - var node = new NodeModel(new Point(x, y)); - node.AddPort(PortAlignment.Bottom); - node.AddPort(PortAlignment.Top); - node.AddPort(PortAlignment.Left); - node.AddPort(PortAlignment.Right); - return node; - } + private NodeModel NewNode(double x, double y) + { + var node = new NodeModel(new Point(x, y)); + node.AddPort(PortAlignment.Bottom); + node.AddPort(PortAlignment.Top); + node.AddPort(PortAlignment.Left); + node.AddPort(PortAlignment.Right); + return node; } } diff --git a/samples/SharedDemo/Demos/Links/SnappingDemo.razor b/samples/SharedDemo/Demos/Links/SnappingDemo.razor index 414cc359c..6dd9b6f8b 100644 --- a/samples/SharedDemo/Demos/Links/SnappingDemo.razor +++ b/samples/SharedDemo/Demos/Links/SnappingDemo.razor @@ -2,6 +2,6 @@ @layout DemoLayout @inject LayoutData LayoutData - + \ No newline at end of file diff --git a/samples/SharedDemo/Demos/Links/SnappingDemo.razor.cs b/samples/SharedDemo/Demos/Links/SnappingDemo.razor.cs index f8fb376de..33edf7ac8 100644 --- a/samples/SharedDemo/Demos/Links/SnappingDemo.razor.cs +++ b/samples/SharedDemo/Demos/Links/SnappingDemo.razor.cs @@ -1,38 +1,37 @@ -using Blazor.Diagrams.Core; +using Blazor.Diagrams; using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Core.Models; -namespace SharedDemo.Demos.Links +namespace SharedDemo.Demos.Links; + +public partial class SnappingDemo { - public partial class SnappingDemo - { - private Diagram _diagram = new Diagram(); + private BlazorDiagram _blazorDiagram = new BlazorDiagram(); - protected override void OnInitialized() - { - base.OnInitialized(); + protected override void OnInitialized() + { + base.OnInitialized(); - LayoutData.Title = "Link Snapping"; - LayoutData.Info = "While dragging a new link, it will try to find (and link) to the closest target within a radius."; - LayoutData.DataChanged(); + LayoutData.Title = "Link Snapping"; + LayoutData.Info = "While dragging a new link, it will try to find (and link) to the closest target within a radius."; + LayoutData.DataChanged(); - InitializeDiagram(); - } + InitializeDiagram(); + } - private void InitializeDiagram() - { - _diagram.Options.Links.EnableSnapping = true; - _diagram.Nodes.Add(new[] { NewNode(50, 80), NewNode(200, 350), NewNode(400, 100) }); - } + private void InitializeDiagram() + { + _blazorDiagram.Options.Links.EnableSnapping = true; + _blazorDiagram.Nodes.Add(new[] { NewNode(50, 80), NewNode(200, 350), NewNode(400, 100) }); + } - private NodeModel NewNode(double x, double y) - { - var node = new NodeModel(new Point(x, y)); - node.AddPort(PortAlignment.Bottom); - node.AddPort(PortAlignment.Top); - node.AddPort(PortAlignment.Left); - node.AddPort(PortAlignment.Right); - return node; - } + private NodeModel NewNode(double x, double y) + { + var node = new NodeModel(new Point(x, y)); + node.AddPort(PortAlignment.Bottom); + node.AddPort(PortAlignment.Top); + node.AddPort(PortAlignment.Left); + node.AddPort(PortAlignment.Right); + return node; } } diff --git a/samples/SharedDemo/Demos/Links/VerticesDemo.razor b/samples/SharedDemo/Demos/Links/VerticesDemo.razor index 977f35122..0b5379ea1 100644 --- a/samples/SharedDemo/Demos/Links/VerticesDemo.razor +++ b/samples/SharedDemo/Demos/Links/VerticesDemo.razor @@ -2,6 +2,6 @@ @layout DemoLayout @inject LayoutData LayoutData - + \ No newline at end of file diff --git a/samples/SharedDemo/Demos/Links/VerticesDemo.razor.cs b/samples/SharedDemo/Demos/Links/VerticesDemo.razor.cs index d51baac5b..39dfcd39f 100644 --- a/samples/SharedDemo/Demos/Links/VerticesDemo.razor.cs +++ b/samples/SharedDemo/Demos/Links/VerticesDemo.razor.cs @@ -1,62 +1,62 @@ -using Blazor.Diagrams.Core; +using Blazor.Diagrams; using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Core.Models; +using Blazor.Diagrams.Core.PathGenerators; -namespace SharedDemo.Demos.Links +namespace SharedDemo.Demos.Links; + +public partial class VerticesDemo { - public partial class VerticesDemo + private BlazorDiagram _blazorDiagram = new BlazorDiagram(); + + protected override void OnInitialized() { - private Diagram _diagram = new Diagram(); + base.OnInitialized(); - protected override void OnInitialized() - { - base.OnInitialized(); + LayoutData.Title = "Link Vertices"; + LayoutData.Info = "Click on a link to create a vertex. Double click on a vertex to delete it. " + + "You can drag the vertices around."; + LayoutData.DataChanged(); - LayoutData.Title = "Link Vertices"; - LayoutData.Info = "Click on a link to create a vertex. Double click on a vertex to delete it. " + - "You can drag the vertices around."; - LayoutData.DataChanged(); + InitializeDiagram(); + } - InitializeDiagram(); - } + private void InitializeDiagram() + { + var node1 = NewNode(50, 80); + var node2 = NewNode(200, 350); + var node3 = NewNode(400, 100); - private void InitializeDiagram() + _blazorDiagram.Nodes.Add(new[] { node1, node2, node3 }); + + var link1 = new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)) { - var node1 = NewNode(50, 80); - var node2 = NewNode(200, 350); - var node3 = NewNode(400, 100); - - _diagram.Nodes.Add(new[] { node1, node2, node3 }); - - var link1 = new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)) - { - PathGenerator = PathGenerators.Straight, - Segmentable = true - }; - link1.Labels.Add(new LinkLabelModel(link1, "Content")); - link1.Vertices.Add(new LinkVertexModel(link1, new Point(221, 117))); - link1.Vertices.Add(new LinkVertexModel(link1, new Point(111, 291))); - - var link2 = new LinkModel(node2.GetPort(PortAlignment.Right), node3.GetPort(PortAlignment.Left)) - { - PathGenerator = PathGenerators.Smooth, // default - Segmentable = true - }; - link2.Labels.Add(new LinkLabelModel(link2, "Content")); - link2.Vertices.Add(new LinkVertexModel(link2, new Point(400, 324))); - link2.Vertices.Add(new LinkVertexModel(link2, new Point(326, 180))); - - _diagram.Links.Add(new[] { link1, link2 }); - } - - private NodeModel NewNode(double x, double y) + PathGenerator = new StraightPathGenerator(), + Segmentable = true + }; + link1.Labels.Add(new LinkLabelModel(link1, "Content")); + link1.Vertices.Add(new LinkVertexModel(link1, new Point(221, 117))); + link1.Vertices.Add(new LinkVertexModel(link1, new Point(111, 291))); + + var link2 = new LinkModel(node2.GetPort(PortAlignment.Right), node3.GetPort(PortAlignment.Left)) { - var node = new NodeModel(new Point(x, y)); - node.AddPort(PortAlignment.Bottom); - node.AddPort(PortAlignment.Top); - node.AddPort(PortAlignment.Left); - node.AddPort(PortAlignment.Right); - return node; - } + PathGenerator = new SmoothPathGenerator(), // default + Segmentable = true + }; + link2.Labels.Add(new LinkLabelModel(link2, "Content")); + link2.Vertices.Add(new LinkVertexModel(link2, new Point(400, 324))); + link2.Vertices.Add(new LinkVertexModel(link2, new Point(326, 180))); + + _blazorDiagram.Links.Add(new[] { link1, link2 }); + } + + private NodeModel NewNode(double x, double y) + { + var node = new NodeModel(new Point(x, y)); + node.AddPort(PortAlignment.Bottom); + node.AddPort(PortAlignment.Top); + node.AddPort(PortAlignment.Left); + node.AddPort(PortAlignment.Right); + return node; } } diff --git a/samples/SharedDemo/Demos/Locked.razor b/samples/SharedDemo/Demos/Locked.razor index 05d122e27..788af122b 100644 --- a/samples/SharedDemo/Demos/Locked.razor +++ b/samples/SharedDemo/Demos/Locked.razor @@ -16,6 +16,6 @@ } } - + diff --git a/samples/SharedDemo/Demos/Locked.razor.cs b/samples/SharedDemo/Demos/Locked.razor.cs index a4e43536d..31fb668ae 100644 --- a/samples/SharedDemo/Demos/Locked.razor.cs +++ b/samples/SharedDemo/Demos/Locked.razor.cs @@ -1,38 +1,37 @@ -using Blazor.Diagrams.Core; +using Blazor.Diagrams; using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Core.Models; using Microsoft.AspNetCore.Components; -namespace SharedDemo -{ - public class LockedComponent : ComponentBase - { - protected readonly Diagram diagram = new Diagram(); +namespace SharedDemo; - protected override void OnInitialized() - { - base.OnInitialized(); +public class LockedComponent : ComponentBase +{ + protected readonly BlazorDiagram BlazorDiagram = new BlazorDiagram(); - var node1 = NewNode(50, 50); - var node2 = NewNode(300, 300); - diagram.Nodes.Add(new[] { node1, node2, NewNode(300, 50) }); + protected override void OnInitialized() + { + base.OnInitialized(); - var link = new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)) - { - Locked = true - }; - diagram.Links.Add(link); - } + var node1 = NewNode(50, 50); + var node2 = NewNode(300, 300); + BlazorDiagram.Nodes.Add(new[] { node1, node2, NewNode(300, 50) }); - private NodeModel NewNode(double x, double y) + var link = new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)) { - var node = new NodeModel(new Point(x, y)); - node.AddPort(PortAlignment.Bottom); - node.AddPort(PortAlignment.Top).Locked = true; - node.AddPort(PortAlignment.Left); - node.AddPort(PortAlignment.Right); - node.Locked = true; - return node; - } + Locked = true + }; + BlazorDiagram.Links.Add(link); + } + + private NodeModel NewNode(double x, double y) + { + var node = new NodeModel(new Point(x, y)); + node.AddPort(PortAlignment.Bottom); + node.AddPort(PortAlignment.Top).Locked = true; + node.AddPort(PortAlignment.Left); + node.AddPort(PortAlignment.Right); + node.Locked = true; + return node; } } diff --git a/samples/SharedDemo/Demos/Nodes/PortlessLinks.razor b/samples/SharedDemo/Demos/Nodes/PortlessLinks.razor index bad7eadd1..1836088ce 100644 --- a/samples/SharedDemo/Demos/Nodes/PortlessLinks.razor +++ b/samples/SharedDemo/Demos/Nodes/PortlessLinks.razor @@ -2,6 +2,13 @@ @layout DemoLayout @inject LayoutData LayoutData - - + + + + + + + \ No newline at end of file diff --git a/samples/SharedDemo/Demos/Nodes/PortlessLinks.razor.cs b/samples/SharedDemo/Demos/Nodes/PortlessLinks.razor.cs index a0aaa84fc..a9d807073 100644 --- a/samples/SharedDemo/Demos/Nodes/PortlessLinks.razor.cs +++ b/samples/SharedDemo/Demos/Nodes/PortlessLinks.razor.cs @@ -1,46 +1,77 @@ using Blazor.Diagrams.Core.Models; -using Blazor.Diagrams.Core; -using System; -using System.Collections.Generic; -using System.Text; using Blazor.Diagrams.Core.Geometry; +using Blazor.Diagrams; +using Blazor.Diagrams.Core.Anchors; +using Blazor.Diagrams.Core.Controls.Default; -namespace SharedDemo.Demos.Nodes +namespace SharedDemo.Demos.Nodes; + +public partial class PortlessLinks { - public partial class PortlessLinks + private BlazorDiagram _blazorDiagram = new BlazorDiagram(); + + protected override void OnInitialized() { - private Diagram _diagram = new Diagram(); + base.OnInitialized(); - protected override void OnInitialized() - { - base.OnInitialized(); + LayoutData.Title = "Portless Links"; + LayoutData.Info = "Starting from 2.0, you can create links between nodes directly! " + + "All you need to specify is the shape of your nodes in order to calculate the connection points."; + LayoutData.DataChanged(); - LayoutData.Title = "Portless Links"; - LayoutData.Info = "Starting from 2.0, you can create links between nodes directly! " + - "All you need to specify is the shape of your nodes in order to calculate the connection points."; - LayoutData.DataChanged(); + InitializeDiagram(); + } - InitializeDiagram(); - } + private void InitializeDiagram() + { + _blazorDiagram.RegisterComponent(); - private void InitializeDiagram() + var node1 = new NodeModel(new Point(80, 80)); + var node2 = new RoundedNode(new Point(280, 150)); + var node3 = new NodeModel(new Point(400, 300)); + node3.AddPort(PortAlignment.Left); + _blazorDiagram.Nodes.Add(node1); + _blazorDiagram.Nodes.Add(node2); + _blazorDiagram.Nodes.Add(node3); + _blazorDiagram.Links.Add(new LinkModel(node1, node2) + { + SourceMarker = LinkMarker.Arrow, + TargetMarker = LinkMarker.Arrow, + Segmentable = true + }); + _blazorDiagram.Links.Add(new LinkModel(new ShapeIntersectionAnchor(node2), + new SinglePortAnchor(node3.GetPort(PortAlignment.Left))) { - _diagram.RegisterModelComponent(); - - var node1 = new NodeModel(new Point(80, 80), shape: Shapes.Rectangle); - var node2 = new RoundedNode(new Point(280, 150), shape: Shapes.Circle); - _diagram.Nodes.Add(node1); - _diagram.Nodes.Add(node2); - _diagram.Links.Add(new LinkModel(node1, node2) - { - SourceMarker = LinkMarker.Arrow, - TargetMarker = LinkMarker.Arrow - }); - } + SourceMarker = LinkMarker.Arrow, + TargetMarker = LinkMarker.Arrow, + Segmentable = true + }); + + _blazorDiagram.Controls.AddFor(node1) + .Add(new RemoveControl(1, 0)) + .Add(new DragNewLinkControl(1, 0.5, 20)) + .Add(new BoundaryControl()); + + _blazorDiagram.Controls.AddFor(node2) + .Add(new RemoveControl(1, 0)) + .Add(new DragNewLinkControl(1, 0.5, 20)) + .Add(new BoundaryControl()); + + _blazorDiagram.Controls.AddFor(node3) + .Add(new RemoveControl(1, 0)) + .Add(new DragNewLinkControl(1, 0.5, 20)) + .Add(new BoundaryControl()); } +} - class RoundedNode : NodeModel +class RoundedNode : NodeModel +{ + public RoundedNode(Point position = null) : base(position) { - public RoundedNode(Point position = null, ShapeDefiner shape = null) : base(position, RenderLayer.HTML, shape) { } } -} + + public override IShape GetShape() + { + return Shapes.Circle(this); + } +} \ No newline at end of file diff --git a/samples/SharedDemo/Demos/Nodes/SvgDemo.razor b/samples/SharedDemo/Demos/Nodes/SvgDemo.razor index dd14d327f..4fcbaecc6 100644 --- a/samples/SharedDemo/Demos/Nodes/SvgDemo.razor +++ b/samples/SharedDemo/Demos/Nodes/SvgDemo.razor @@ -2,6 +2,6 @@ @layout DemoLayout @inject LayoutData LayoutData - + \ No newline at end of file diff --git a/samples/SharedDemo/Demos/Nodes/SvgDemo.razor.cs b/samples/SharedDemo/Demos/Nodes/SvgDemo.razor.cs index 44f49104e..85cc04c64 100644 --- a/samples/SharedDemo/Demos/Nodes/SvgDemo.razor.cs +++ b/samples/SharedDemo/Demos/Nodes/SvgDemo.razor.cs @@ -1,41 +1,61 @@ -using Blazor.Diagrams.Core; +using Blazor.Diagrams; +using Blazor.Diagrams.Components; using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Core.Models; +using Blazor.Diagrams.Core.Controls.Default; +using Blazor.Diagrams.Models; -namespace SharedDemo.Demos.Nodes +namespace SharedDemo.Demos.Nodes; + +public partial class SvgDemo { - public partial class SvgDemo + private BlazorDiagram _blazorDiagram = new BlazorDiagram(); + + protected override void OnInitialized() + { + base.OnInitialized(); + + LayoutData.Title = "SVG Nodes"; + LayoutData.Info = "You can also have SVG nodes! All you need to do is to set the Layer to RenderLayer.SVG."; + LayoutData.DataChanged(); + + InitializeDiagram(); + } + + private void InitializeDiagram() + { + _blazorDiagram.RegisterComponent(); + _blazorDiagram.RegisterComponent(); + _blazorDiagram.RegisterComponent(); + + var node1 = NewNode(50, 50); + var node2 = NewNode(250, 250); + var node3 = NewNode(500, 100); + var node4 = NewNode(700, 350); + _blazorDiagram.Nodes.Add(new[] { node1, node2, node3, node4 }); + + var group1 = _blazorDiagram.Groups.Add(new SvgGroupModel(new[] { node1, node2 })); + var group2 = _blazorDiagram.Groups.Add(new SvgGroupModel(new[] { group1, node3 })); + + _blazorDiagram.Links.Add(new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left))); + _blazorDiagram.Links.Add(new LinkModel(node2.GetPort(PortAlignment.Right), node3.GetPort(PortAlignment.Left))); + _blazorDiagram.Links.Add(new LinkModel(node1.GetPort(PortAlignment.Right), node3.GetPort(PortAlignment.Left))); + var link = _blazorDiagram.Links.Add(new LinkModel(group2, node4)); + + var controls1 = _blazorDiagram.Controls.AddFor(node4); + controls1.Add(new RemoveControl(1, 0)); + controls1.Add(new BoundaryControl()); + + var controls2 = _blazorDiagram.Controls.AddFor(link); + controls2.Add(new RemoveControl(1, 0)); + controls2.Add(new BoundaryControl()); + } + + private NodeModel NewNode(double x, double y, bool svg = true) { - private Diagram _diagram = new Diagram(); - - protected override void OnInitialized() - { - base.OnInitialized(); - - LayoutData.Title = "SVG Nodes"; - LayoutData.Info = "You can also have SVG nodes! All you need to do is to set the Layer to RenderLayer.SVG."; - LayoutData.DataChanged(); - - InitializeDiagram(); - } - - private void InitializeDiagram() - { - _diagram.Options.DefaultNodeComponent = typeof(SvgNodeWidget); - - var node1 = NewNode(80, 80); - var node2 = NewNode(280, 150); - _diagram.Nodes.Add(node1); - _diagram.Nodes.Add(node2); - _diagram.Links.Add(new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left))); - } - - private NodeModel NewNode(double x, double y) - { - var node = new NodeModel(new Point(x, y), RenderLayer.SVG); - node.AddPort(PortAlignment.Left); - node.AddPort(PortAlignment.Right); - return node; - } + var node = svg ? new SvgNodeModel(new Point(x, y)) : new NodeModel(new Point(x, y)); + node.AddPort(PortAlignment.Left); + node.AddPort(PortAlignment.Right); + return node; } } diff --git a/samples/SharedDemo/Demos/Nodes/SvgNodeWidget.razor b/samples/SharedDemo/Demos/Nodes/SvgNodeWidget.razor index 5e2f159f2..932f138f0 100644 --- a/samples/SharedDemo/Demos/Nodes/SvgNodeWidget.razor +++ b/samples/SharedDemo/Demos/Nodes/SvgNodeWidget.razor @@ -1,12 +1,12 @@ - - + - + @code { diff --git a/samples/SharedDemo/Demos/Performance.razor b/samples/SharedDemo/Demos/Performance.razor index c3c45b851..6e5c2da97 100644 --- a/samples/SharedDemo/Demos/Performance.razor +++ b/samples/SharedDemo/Demos/Performance.razor @@ -14,6 +14,6 @@ } } - + \ No newline at end of file diff --git a/samples/SharedDemo/Demos/Performance.razor.cs b/samples/SharedDemo/Demos/Performance.razor.cs index 3a04162d9..76d9c4859 100644 --- a/samples/SharedDemo/Demos/Performance.razor.cs +++ b/samples/SharedDemo/Demos/Performance.razor.cs @@ -1,31 +1,30 @@ -using Blazor.Diagrams.Core; +using Blazor.Diagrams; +using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Core.Models; using Microsoft.AspNetCore.Components; -using Blazor.Diagrams.Core.Geometry; -namespace SharedDemo.Demos +namespace SharedDemo.Demos; + +public class PerformanceCompoent : ComponentBase { - public class PerformanceCompoent : ComponentBase + protected readonly BlazorDiagram BlazorDiagram = new BlazorDiagram(); + + protected override void OnInitialized() { - protected readonly Diagram diagram = new Diagram(); + base.OnInitialized(); - protected override void OnInitialized() + for (int r = 0; r < 10; r++) { - base.OnInitialized(); - - for (int r = 0; r < 10; r++) + for (int c = 0; c < 10; c += 2) { - for (int c = 0; c < 10; c += 2) - { - var node1 = new NodeModel(new Point(10 + c * 10 + c * 120, 10 + r * 100)); - var node2 = new NodeModel(new Point(10 + (c + 1) * 130, 10 + r * 100)); + var node1 = new NodeModel(new Point(10 + c * 10 + c * 120, 10 + r * 100)); + var node2 = new NodeModel(new Point(10 + (c + 1) * 130, 10 + r * 100)); - var sourcePort = node1.AddPort(PortAlignment.Right); - var targetPort = node2.AddPort(PortAlignment.Left); + var sourcePort = node1.AddPort(PortAlignment.Right); + var targetPort = node2.AddPort(PortAlignment.Left); - diagram.Nodes.Add(new[] { node1, node2 }); - diagram.Links.Add(new LinkModel(sourcePort, targetPort)); - } + BlazorDiagram.Nodes.Add(new[] { node1, node2 }); + BlazorDiagram.Links.Add(new LinkModel(sourcePort, targetPort)); } } } diff --git a/samples/SharedDemo/Demos/Simple.razor b/samples/SharedDemo/Demos/Simple.razor index 26cfc86b2..9fa10df97 100644 --- a/samples/SharedDemo/Demos/Simple.razor +++ b/samples/SharedDemo/Demos/Simple.razor @@ -4,6 +4,7 @@ @inject LayoutData LayoutData @code { + protected override void OnInitialized() { base.OnInitialized(); @@ -12,27 +13,32 @@ LayoutData.Info = "A simple example of Blazor.Diagrams."; LayoutData.DataChanged(); } + }
- +
- +
- +
- + - + + + - + \ No newline at end of file diff --git a/samples/SharedDemo/Demos/Simple.razor.cs b/samples/SharedDemo/Demos/Simple.razor.cs index c725c00b9..316fd4c20 100644 --- a/samples/SharedDemo/Demos/Simple.razor.cs +++ b/samples/SharedDemo/Demos/Simple.razor.cs @@ -1,52 +1,53 @@ -using Blazor.Diagrams.Core; +using Blazor.Diagrams; using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Core.Models; +using Blazor.Diagrams.Core.PathGenerators; +using Blazor.Diagrams.Core.Routers; using Microsoft.AspNetCore.Components; -namespace SharedDemo +namespace SharedDemo; + +public class SimpleComponent : ComponentBase { - public class SimpleComponent : ComponentBase + protected readonly BlazorDiagram BlazorDiagram = new BlazorDiagram(); + + protected override void OnInitialized() { - protected readonly Diagram diagram = new Diagram(); + base.OnInitialized(); + + var node1 = NewNode(50, 50); + var node2 = NewNode(300, 300); + var node3 = NewNode(300, 50); + BlazorDiagram.Nodes.Add(new[] { node1, node2, node3 }); - protected override void OnInitialized() + BlazorDiagram.Links.Add(new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)) { - base.OnInitialized(); - - var node1 = NewNode(50, 50); - var node2 = NewNode(300, 300); - var node3 = NewNode(300, 50); - diagram.Nodes.Add(new[] { node1, node2, node3 }); - - diagram.Links.Add(new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left)) - { - SourceMarker = LinkMarker.Arrow, - TargetMarker = LinkMarker.Arrow - }); - diagram.Links.Add(new LinkModel(node2.GetPort(PortAlignment.Right), node3.GetPort(PortAlignment.Right)) - { - Router = Routers.Orthogonal, - PathGenerator = PathGenerators.Straight, - SourceMarker = LinkMarker.Arrow, - TargetMarker = LinkMarker.Arrow - }); - } - - protected void ToggleZoom() => diagram.Options.Zoom.Enabled = !diagram.Options.Zoom.Enabled; - - protected void TogglePanning() => diagram.Options.AllowPanning = !diagram.Options.AllowPanning; - - protected void ToggleVirtualization() - => diagram.Options.EnableVirtualization = !diagram.Options.EnableVirtualization; - - private NodeModel NewNode(double x, double y) + SourceMarker = LinkMarker.Arrow, + TargetMarker = LinkMarker.Arrow + }); + BlazorDiagram.Links.Add(new LinkModel(node2.GetPort(PortAlignment.Right), node3.GetPort(PortAlignment.Right)) { - var node = new NodeModel(new Point(x, y)); - node.AddPort(PortAlignment.Bottom); - node.AddPort(PortAlignment.Top); - node.AddPort(PortAlignment.Left); - node.AddPort(PortAlignment.Right); - return node; - } + Router = new OrthogonalRouter(), + PathGenerator = new StraightPathGenerator(), + SourceMarker = LinkMarker.Arrow, + TargetMarker = LinkMarker.Arrow + }); + } + + protected void ToggleZoom() => BlazorDiagram.Options.Zoom.Enabled = !BlazorDiagram.Options.Zoom.Enabled; + + protected void TogglePanning() => BlazorDiagram.Options.AllowPanning = !BlazorDiagram.Options.AllowPanning; + + protected void ToggleVirtualization() + => BlazorDiagram.Options.Virtualization.Enabled = !BlazorDiagram.Options.Virtualization.Enabled; + + private NodeModel NewNode(double x, double y) + { + var node = new NodeModel(new Point(x, y)); + node.AddPort(PortAlignment.Bottom); + node.AddPort(PortAlignment.Top); + node.AddPort(PortAlignment.Left); + node.AddPort(PortAlignment.Right); + return node; } } diff --git a/samples/SharedDemo/Demos/SnapToGrid.razor b/samples/SharedDemo/Demos/SnapToGrid.razor index e1c2de7a9..9b1e9a256 100644 --- a/samples/SharedDemo/Demos/SnapToGrid.razor +++ b/samples/SharedDemo/Demos/SnapToGrid.razor @@ -9,16 +9,23 @@ base.OnInitialized(); LayoutData.Title = "Snap to Grid"; - LayoutData.Info = "This diagram has a grid size of 50, moving nodes will make them automatically snap.
" + + LayoutData.Info = "This diagram has a grid size of 75, moving nodes will make them automatically snap.
" + "The background grid isn't added by Z.Blazor.Diagrams, in order for you to use whatever you want."; LayoutData.DataChanged(); } } +
+
+ + +
+
- - + + - + + diff --git a/samples/SharedDemo/Demos/SnapToGrid.razor.cs b/samples/SharedDemo/Demos/SnapToGrid.razor.cs index 8e4902e7c..bba495dd2 100644 --- a/samples/SharedDemo/Demos/SnapToGrid.razor.cs +++ b/samples/SharedDemo/Demos/SnapToGrid.razor.cs @@ -1,35 +1,35 @@ -using Blazor.Diagrams.Core; +using Blazor.Diagrams; using Blazor.Diagrams.Core.Geometry; using Blazor.Diagrams.Core.Models; +using Blazor.Diagrams.Options; using Microsoft.AspNetCore.Components; -namespace SharedDemo +namespace SharedDemo; + +public class SnapToGridComponent : ComponentBase { - public class SnapToGridComponent : ComponentBase + protected readonly BlazorDiagram BlazorDiagram = new(new BlazorDiagramOptions { - protected readonly Diagram diagram = new Diagram(new DiagramOptions - { - GridSize = 50 - }); + GridSize = 75 + }); - protected override void OnInitialized() - { - base.OnInitialized(); + protected override void OnInitialized() + { + base.OnInitialized(); - var node1 = NewNode(50, 50); - var node2 = NewNode(300, 300); - diagram.Links.Add(new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left))); - diagram.Nodes.Add(new[] { node1, node2, NewNode(300, 50) }); - } + var node1 = NewNode(50, 50); + var node2 = NewNode(300, 300); + BlazorDiagram.Links.Add(new LinkModel(node1.GetPort(PortAlignment.Right), node2.GetPort(PortAlignment.Left))); + BlazorDiagram.Nodes.Add(new[] { node1, node2, NewNode(300, 50) }); + } - private NodeModel NewNode(double x, double y) - { - var node = new NodeModel(new Point(x, y)); - node.AddPort(PortAlignment.Bottom); - node.AddPort(PortAlignment.Top); - node.AddPort(PortAlignment.Left); - node.AddPort(PortAlignment.Right); - return node; - } + private NodeModel NewNode(double x, double y) + { + var node = new NodeModel(new Point(x, y)); + node.AddPort(PortAlignment.Bottom); + node.AddPort(PortAlignment.Top); + node.AddPort(PortAlignment.Left); + node.AddPort(PortAlignment.Right); + return node; } } diff --git a/samples/SharedDemo/Demos/ZoomToFit.razor b/samples/SharedDemo/Demos/ZoomToFit.razor index 341b9a5ad..b9df4fd98 100644 --- a/samples/SharedDemo/Demos/ZoomToFit.razor +++ b/samples/SharedDemo/Demos/ZoomToFit.razor @@ -17,8 +17,8 @@ + @onclick="() => BlazorDiagram.ZoomToFit(50)">Zoom to fit - + diff --git a/samples/SharedDemo/Demos/ZoomToFit.razor.cs b/samples/SharedDemo/Demos/ZoomToFit.razor.cs index 70871063b..a859137f1 100644 --- a/samples/SharedDemo/Demos/ZoomToFit.razor.cs +++ b/samples/SharedDemo/Demos/ZoomToFit.razor.cs @@ -1,31 +1,30 @@ -using Blazor.Diagrams.Core.Models; -using Blazor.Diagrams.Core; -using Microsoft.AspNetCore.Components; +using Blazor.Diagrams; using Blazor.Diagrams.Core.Geometry; +using Blazor.Diagrams.Core.Models; +using Microsoft.AspNetCore.Components; + +namespace SharedDemo.Demos; -namespace SharedDemo.Demos +public class ZoomToFitComponent : ComponentBase { - public class ZoomToFitComponent : ComponentBase + protected readonly BlazorDiagram BlazorDiagram = new BlazorDiagram(); + + protected override void OnInitialized() { - protected readonly Diagram diagram = new Diagram(); + base.OnInitialized(); - protected override void OnInitialized() + for (int r = 0; r < 8; r++) { - base.OnInitialized(); - - for (int r = 0; r < 8; r++) + for (int c = 0; c < 8; c += 2) { - for (int c = 0; c < 8; c += 2) - { - var node1 = new NodeModel(new Point(350 + c * 80 + c * 120, 150 + r * 120)); - var node2 = new NodeModel(new Point(350 + (c + 1) * 200, 150 + r * 120)); + var node1 = new NodeModel(new Point(350 + c * 80 + c * 120, 150 + r * 120)); + var node2 = new NodeModel(new Point(350 + (c + 1) * 200, 150 + r * 120)); - var sourcePort = node1.AddPort(PortAlignment.Right); - var targetPort = node2.AddPort(PortAlignment.Left); + var sourcePort = node1.AddPort(PortAlignment.Right); + var targetPort = node2.AddPort(PortAlignment.Left); - diagram.Nodes.Add(new[] { node1, node2 }); - diagram.Links.Add(new LinkModel(sourcePort, targetPort)); - } + BlazorDiagram.Nodes.Add(new[] { node1, node2 }); + BlazorDiagram.Links.Add(new LinkModel(sourcePort, targetPort)); } } } diff --git a/samples/SharedDemo/DocPage.cs b/samples/SharedDemo/DocPage.cs index 5c83884ab..19c6263cc 100644 --- a/samples/SharedDemo/DocPage.cs +++ b/samples/SharedDemo/DocPage.cs @@ -2,18 +2,17 @@ using Microsoft.JSInterop; using System.Threading.Tasks; -namespace SharedDemo +namespace SharedDemo; + +public class DocPage : ComponentBase { - public class DocPage : ComponentBase - { - [Inject] - private IJSRuntime JsRuntime { get; set; } + [Inject] + private IJSRuntime JsRuntime { get; set; } - protected override async Task OnAfterRenderAsync(bool firstRender) - { - await base.OnAfterRenderAsync(firstRender); + protected override async Task OnAfterRenderAsync(bool firstRender) + { + await base.OnAfterRenderAsync(firstRender); - await JsRuntime.InvokeVoidAsync("setup"); - } + await JsRuntime.InvokeVoidAsync("setup"); } } diff --git a/samples/SharedDemo/LayoutData.cs b/samples/SharedDemo/LayoutData.cs index 34cd613b4..20c90ddb3 100644 --- a/samples/SharedDemo/LayoutData.cs +++ b/samples/SharedDemo/LayoutData.cs @@ -1,15 +1,14 @@ using System; -namespace SharedDemo +namespace SharedDemo; + +public class LayoutData { - public class LayoutData - { - public string Title { get; set; } - public string Icon { get; set; } - public string Date { get; set; } - public string Info { get; set; } + public string Title { get; set; } + public string Icon { get; set; } + public string Date { get; set; } + public string Info { get; set; } - public Action OnDataChanged { get; set; } - public void DataChanged() => OnDataChanged?.Invoke(); - } + public Action OnDataChanged { get; set; } + public void DataChanged() => OnDataChanged?.Invoke(); } diff --git a/samples/SharedDemo/Layouts/DemoLayout.razor b/samples/SharedDemo/Layouts/DemoLayout.razor index 516906f42..4366580a7 100644 --- a/samples/SharedDemo/Layouts/DemoLayout.razor +++ b/samples/SharedDemo/Layouts/DemoLayout.razor @@ -21,7 +21,7 @@ @if (LayoutData.Info != null) { - \r\n\t\treflect theto completebecame moreradioactiverejected bywithout anyhis father,which couldcopy of theto indicatea politicalaccounts ofconstitutesworked witherof his lifeaccompaniedclientWidthprevent theLegislativedifferentlytogether inhas severalfor anothertext of thefounded thee with the is used forchanged theusually theplace wherewhereas the> \nHowever thelead to the\tThe currentthe site ofsubstantialexperience,in the Westthey shouldslovenD\rinacomentariosuniversidadcondicionesactividadesexperienciatecnologC-aproducciC3npuntuaciC3naplicaciC3ncontraseC1acategorC-asregistrarseprofesionaltratamientoregC-stratesecretarC-aprincipalesprotecciC3nimportantesimportanciaposibilidadinteresantecrecimientonecesidadessuscribirseasociaciC3ndisponiblesevaluaciC3nestudiantesresponsableresoluciC3nguadalajararegistradosoportunidadcomercialesfotografC-aautoridadesingenierC-atelevisiC3ncompetenciaoperacionesestablecidosimplementeactualmentenavegaciC3nconformidadline-height:font-family:\" : \"http://applicationslink\" href=\"specifically//\n/index.html\"window.open( !important;application/independence//www.googleorganizationautocompleterequirementsconservative
most notably/>notification'undefined')Furthermore,believe thatinnerHTML = prior to thedramaticallyreferring tonegotiationsheadquartersSouth AfricaunsuccessfulPennsylvaniaAs a result,\npadding-top:experimentalgetAttributeinstructionstechnologiespart of the =function(){subscriptionl.dtd\">\r\nEnglish (US)appendChild(transmissions. However, intelligence\" tabindex=\"float:right;Commonwealthranging fromin which theat least onereproductionencyclopedia;font-size:1jurisdictionat that time\">compensationchampionshipmedia=\"all\" violation ofreference toreturn true;Strict//EN\" transactionsinterventionverificationInformation difficultiesChampionshipcapabilities}\n\nChristianityfor example,Professionalrestrictionssuggest thatwas released(such as theremoveClass(unemploymentthe Americanstructure of/index.html published inspan class=\"\">\n\nf (document.border: 1px {font-size:1treatment of0\" height=\"1modificationIndependencedivided intogreater thanachievementsestablishingJavaScript\" neverthelesssignificanceBroadcasting> container\">\nsuch as the influence ofa particularsrc='http://navigation\" half of the substantial  advantage ofdiscovery offundamental metropolitanthe opposite\" xml:lang=\"deliberatelyalign=centerevolution ofpreservationimprovementsbeginning inJesus ChristPublicationsdisagreementtext-align:r, function()similaritiesbody>is currentlyalphabeticalis sometimestype=\"image/many of the flow:hidden;available indescribe theexistence ofall over thethe Internet\t