All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
ZoomBehavior
using new zoom before Clamp to set Pan. (fixes #141)PanChanged
not triggering when zooming with the mouse wheel.- Zoom value decreasing when the mouse wheel delta is zero.
- Ports aren't refreshed when links are added in
OnInitializedAsync
. (fixes #111)
- Links not being removed from the node after they have been removed from the Links layer. (fixes #136)
- A regression in
ZoomToFit
. (fixes #138)
MouseDoubleClick
(500ms interval) event inDiagram
.GetScreenPoint
inDiagram
in order to get the screen points from a diagram point (e.g. node position).Title
property inNodeModel
, used by the default node widget.
ZoomToFit
not triggeringZoomChanged
event.SourceNode
andTargetNode
not being set inBaseLinkModel
when the ports change.
- Multiple demo projects by TrevorDArcyEvans showing:
- Minimal project setup
- Custom nodes & links
- GraphShape layout algorithms
- Link labels not appearing (fixes #109).
ZoomToFit
throwing aNullReferenceException
when one of the nodes doesn't have a size yet (fixes #118).
- Inability to interact with nodes after re-using ids on new node instances.
- Exception when navigating to the Options page (#95).
- Portless links not deleted when node is deleted (#96).
ScaleFactor
zoom option (@joezearing)- Add
Constraints
options which gives you more control on what happens in the diagram:ShouldDeleteNode
: Whether a selected node should be deleted or notShouldDeleteLink
: Whether a selected link should be deleted or notShouldDeleteGroup
: Whether a selected group should be deleted or not
DeleteSelectionBehavior
unit tests
GroupUngrouped
event (not the greatest name 😄)- Touch events
TouchStart
,TouchMove
andTouchEnd
- Mobile support
- Dragging new links from ports
- Selecting models
- Panning
- Dragging movables
RemoveGroup
method to delete a group and all its children- Pressing DEL on a selected group will now remove it
- Ability for links to be segmentable (by setting
Segmentable
totrue
)- Clicking a segmentable link will add a new vertex in that position
- Vertices are movable models, which mean you can drag them to reposition them
- Double clicking a vertex will delete it
- Link routers
- Routers are functions that take into account a link's vertices, and decide whether to add more points along the path
- They are specified using
Options.Links.DefaultRouter
or by settingRouter
in links - There are currently two routers,
Routers.Normal
andRouters.Orthogonal
- You can provide your own router by simply respecting the delegate
Router
- Link path generators
- Path generators are functions that takes as input a link's route, and return a list of generated SVG paths (strings), as well as the position and angle of the source/target markers
- They are specified using
Options.Links.DefaultPathGenerator
or by settingPathGenerator
in links - There are currently two generators,
PathGenerators.Straight
andPathGenerators.Smooth
- You can provide your own generator by simply respecting the delegate
PathGenerator
- On-the-fly link markers
- A link can either have a
SourceMarker
orTargetMarker
- Link markers are SVG Paths with a known width (to calculate angle and where to cut the links)
- Static markers are available (e.g.
LinkMarker.Arrow
) as well as utility methods to create known shapes
- A link can either have a
MouseClick
event, which only fires if the model (or canvas) in question didn't move, as opposed to MouseUpdata-X-id
HTML attributes to nodes, ports and links- Abstract
BaseLinkModel
,LinkModel
now inherits from it- All the parts of the library now refer to
BaseLinkModel
instead ofLinkModel
(e.g. PortModel.Links)
- All the parts of the library now refer to
Color
,SelectedColor
andWidth
properties toLinkModel
- Link labels
- Can have custom models, using
RegisterModelComponent
- Due to the limitation of SVGs in Blazor, labels aren't interactive and must be created using
MarkupString
- They can have a specified distance
- A number between 0 and 1: Position relative to the link's length
- A positive number, greater than 1: Position away from the start
- A negative number, less than 0: Position away from the end
- They can have an offset (Point)
- Can have custom models, using
- Link snapping
- While the user is dragging a link, it will try to find the closest port it can attach the link to
- Options (in
DiagramOptions.Links
):EnableSnapping
andSnappingRadius
GetBounds
extension method onIEnumerable<NodeModel>
- Expose
Padding
property inGroupModel
Factory
option toOptions.Links
- This is a delegate (
BaseLinkModel LinkFactory(DiagramManager diagram, PortModel sourcePort)
) to let you control how links are created
- This is a delegate (
Groups
(of typeDiagramGroupOptions
) option toDiagramOptions
Enabled
option controls whether users are allow to group nodes together or notKeyboardShortcut
(Func<KeyboardEventArgs, bool>
) controls what keys need to be pressed to trigger the behaviorFactory
lets you control how groups are created
GetRelativePoint
method toDiagram
- This method gives the relative mouse point on the canvas
SelectionBoxWidget
- If used, holding SHIFT and clicking then dragging will show a selection box that selects all models intersecting with it
- Minified versions of all assets
- Observe document body mutations to update canvas container
- Ability to add/remove children after the group is created
Diagram
now also inheritsModel
- Ability to suspend refreshes in
Diagram
by settingDiagram.SuspendRefresh
totrue
- As the name suggests, this will stop the method
Refresh
from triggering the eventChanged
, which tries to re-render the UI
- As the name suggests, this will stop the method
Batch(Action action)
inDiagram
.- This is just a helper method that suspends refreshes, runs the action and then refreshes
- This is now used internally in node/link layers to only trigger 1 UI re-render
- Add
FillColor
parameter toNavigatorWidget
- Ability to create links between two nodes directly, without needing ports
- This depends on the shape of the nodes, which can be defined by providing a
ShapeDefiner
inNodeModel
's constructor - The default shape definer is
Shapes.Rectangle
- Currently, there is only the Rectangle and Ellipse (including Circle) shapes, others will be added later
- This also works for groups, since groups are nodes
- This depends on the shape of the nodes, which can be defined by providing a
- Unit tests
- Renamed
DiagramManager
toDiagram
- Remove need to specify
Name
in diagram'sCascadingValue
- Separate Nodes/Links from DiagramManager, they are now layers (
Diagram.Nodes
andDiagram.Links
) -
- Adding/Removing nodes or links is now done inside these layers (e.g.
Diagram.Nodes.Add
) - Added/Removed events are now inside these layers, not in the diagram (e.g.
Diagram.Links.Added
)
- Adding/Removing nodes or links is now done inside these layers (e.g.
LinkAttached
event removed (TargetPortChanged
is the alternative)- It is now mandatory to add nodes to diagram before creating groups
SelectionChanged
event only contains the model now, useSelected
property- Removed
SelectedModels
in favor ofGetSelectedModels()
, this is because we don't hold a list of selected models anymore (unnecessary) - Renamed
DiagramSubManager
toBehavior
, it makes more sense RegisterBehavior
now takes as an argument the behavior instance to add. No need to useActivator.CreateInstance
for something like this, as it just slows things down- Removed
LinkType
enum - Removed
DefaultLinkType
link option - Removed
DefaultLinkModel
link option - Removed
GetNodesRect
method from DiagramManager (useGetBounds
) - Removed diagram dependency from
GroupModel
(was only usingGetNodesRect
) - Renamed
GetRelativePoint
toGetRelativeMousePoint
- This method gives the relative mouse point inside the diagram, taking into account the current pan & zoom
Widgets
are inside theDiagramCanvas
now- This change is necessary so that widgets with absolute position have their relative parent be the canvas
- Renamed
Navigator
widget toNavigatorWidget
- Allow empty groups
- Compare received JS sizes (width and height) with precision of 0.0001
- In most cases, sizes retrieved from JS (especially with a zoom <> 1) can't be compared accurately (e.g.
80
and79.9999975
). We fix this by comparing with a tolerance.
- In most cases, sizes retrieved from JS (especially with a zoom <> 1) can't be compared accurately (e.g.
- Update ports dimensions only if Initialized is false
- This avoids useless re-renders/JS calls when node is re-visible
NodeModel.Ports
is now aIReadOnlyList<PortModel>
BaseLinkModelExtensions
is now obsolete- Moved everything in
Blazor.Diagrams.Core.Models.Core
toBlazor.Diagrams.Core.Geometry
- This includes
Point
,Size
andRectangle
- This is to better structure things in the project, the new
Geometry
namespace will contain many other things related to it
- This includes
- Only render links when ports/nodes are initialized (position and/or size received)
- This will avoid the weird flicker where links show at (0, 0) then move to the correct position
- Remove links when groups are removed
- Issue where links are clickable outside the visible stroke
pointer-events
is now set tovisiblePainted
instead ofall
MouseUp
event bubbles up fromPortModel
toNodeModel
Size
not taking into account zoom when nodes become visible again- Only allow link creation using left mouse button
- JS errors in razor pages without a diagram
- CustomNodeWidget was movable from text input
- All users who create custom nodes with HTML inputs should use
x:stopPropagation
onmousedown
,mousemove
andmouseup
to prevent the node from being movable through inputs.
- All users who create custom nodes with HTML inputs should use
- Deleted nodes from groups would still show them
NavigatorWidget
not handling negative node positions- Panning with right click. It is now disallowed
- PortRender not taking into account its parent's
RenderLayer
- Ports on SVG nodes will now render as
<g>
elements
- Ports on SVG nodes will now render as
- Useless refreshes when diagram
Container
values didn't change
- Missing MouseUp event on links.
AddGroup
: add an instance of a group to the diagram.- Custom group documentation/demo.
- Clicking the canvas in the Events demo throws an exception.
- The ability to have ports on groups.
- EXPERIMENTAL/INCOMPLETE Nested groups. Since
GroupModel
now inheritsNodeMode
, it became possible to have nested groups, but there are still problems with the order of links between groups. - A
Class
parameter toGroupContainer
.
- Only rerender groups when necessary.
- Receiving the same size from
ResizeObserver
doesn't trigger a rerender anymore. - Avoid rerendering ports twice to update positions.
- Avoid rerendering ports when their parent node is moving.
- Padding is now handled in
GroupModel
instead ofGroupContainer
(UI). This is because the padding is necessary to have accurate size/position in the group model directly.
- Use
@key
when rendering the list of groups. Not using it caused big/weird render times. - Groups not showing in Navigator/Overview.
- Locked nodes now have a
locked
class and their cursor is changed topointer
.
EnableVirtualization
option: whether to only render visible nodes or not.RegisterModelComponent
overload that takesType
s as input for dynamic registrations.
- Two zoom related options,
Minimum
andMaximum
, to clamp the zoom value.
- [BREAKING] Grouped zoom related options into
DiagramZoomOptions
, available unnderOptions.Zoom
.- The option
AllowZooming
was renamed toEnabled
. - The option
InverseZoom
was renamed toInverse
.
- The option
- The diagram canvas' container wasn't updated when the user scrolls (#51).
- Abstract
MovableModel
, which inherits fromSelectableModel
and represents models that can be move with the mouse (e.g. nodes and groups). - Groups widget customization using
RegisterModelComponent
. SizeChanged
event onNodeModel
.
SelectableModel
is now abstract.- Groups:
- Renamed model
Group
toGroupModel
. - Rendered as a single entity (HTML div) with padding.
- Movable and Selectable.
- Selecting a node inside a group doesn't select the others anymore.
- Renamed model
- [BREAKING] Renamed
DiagramManager.ChangePan
toUpdatePan
. - [BREAKING] Renamed
DiagramManager.ChangeZoom
toSetZoom
.
ZoomToFit
wasn't unhiding hidden nodes.
DefaultLinkModel
inDiagramLinkOptions
(@joezearing).- Ability to change source/target ports of a link (
SetSourcePort
andSetTargetPort
).
The methods also trigger the new eventsSourcePortChanged
andTargetPortChanged
.
- Curved link paths now take into account the ports alignements and a margin (@joezearing).
- The
AddLink<T>(T link, PortModel source, PortModel? target = null)
overload inDiagramManager
is now public.
This is useful when developers want to create the link instance themselves,DiagramMananger
will setup ports and trigger appropriate events.
GetMiddleTargetX
andGetMiddleTargetY
usingSourcePort
instead ofTargetPort
(@joezearing).
A new project that aims to group all the algorithms that can be applied to DiagramManager
.
It's a seperate package so that you only include it when you need it.
- Reconnect links to the closest ports (Idea & Initial work by @kolbjornb).
- Diagram Container not ready when ports/nodes need it.
- Drag & Drop demo.
- Helper method
DiagramManager.GetRelativePoint
.
- Diagram container resizes don't update the offsets/position (top/left).
- Container changes don't trigger node visibility checks.
- Ports aren't refreshed when nodes are resized.
- Track mouseup events on nodes @joriskalz.
- Zooming in/out will now trigger the nodes visibility check.
AllowZooming
andAllowPanning
options.DefaultColor
andDefaultSelectedColor
link options.- Custom ports/links demos/documentation.
- Options documentation.
- Group link related options into
DiagramLinkOptions
, available inDiagramOptions.Links
. - All link related calculations (e.g.
MiddleSourceX
) are now extension methods available inLinkModelExtensions
.
LinkWidget
's behind file is not needed anymore.