Skip to content

Commit e86f3e6

Browse files
committed
feat: updated the Resizer behavior to become more predicatable, introduced NodeFlowScope for inherited NodeFlowController access
feat: remove `Using Node Container Builder` section from docs for clarity and alignment with refactored node rendering feat: separate `NodeWidget` and `NodeContainer` for improved modularity feat: optimize rendering and performance with smart culling and improved connection logic
1 parent 6b81c0e commit e86f3e6

22 files changed

+1802
-953
lines changed

packages/vyuh_node_flow/README.md

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ minimap, and more.
4141
- [Building Nodes](#building-nodes)
4242
- [Basic Node Widget](#basic-node-widget)
4343
- [Custom Node Content](#custom-node-content)
44-
- [Using Node Container Builder](#using-node-container-builder)
4544
- [Node Types and Data](#node-types-and-data)
4645
- [Working with Ports](#working-with-ports)
4746
- [Port Basics](#port-basics)
@@ -1068,34 +1067,6 @@ Widget _buildNode(BuildContext context, Node<Map<String, dynamic>> node) {
10681067

10691068
</details>
10701069

1071-
### Using Node Container Builder
1072-
1073-
For complete control over node appearance:
1074-
1075-
<details>
1076-
<summary><strong>Custom Node Container Example</strong></summary>
1077-
1078-
```dart
1079-
NodeFlowEditor<MyData>(
1080-
controller: controller,
1081-
theme: theme,
1082-
nodeBuilder: (context, node) => _buildNodeContent(node),
1083-
nodeContainerBuilder: (context, node, content) {
1084-
// Return NodeWidget with custom styling
1085-
return NodeWidget<MyData>(
1086-
node: node,
1087-
child: content,
1088-
backgroundColor: _getNodeColor(node),
1089-
borderColor: node.isSelected ? Colors.blue : Colors.grey,
1090-
borderWidth: node.isSelected ? 3.0 : 1.0,
1091-
borderRadius: BorderRadius.circular(12),
1092-
);
1093-
},
1094-
)
1095-
```
1096-
1097-
</details>
1098-
10991070
### Node Types and Data
11001071

11011072
Create strongly-typed nodes using sealed classes for type safety and pattern

packages/vyuh_node_flow/lib/editor.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ export 'src/editor/node_flow_behavior.dart';
66
export 'src/editor/node_flow_config.dart';
77
export 'src/editor/node_flow_editor.dart';
88
export 'src/editor/node_flow_events.dart';
9+
export 'src/editor/node_flow_scope.dart';
910
export 'src/editor/node_flow_viewer.dart';

packages/vyuh_node_flow/lib/src/connections/connections_canvas.dart

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
22

33
import '../editor/controller/node_flow_controller.dart';
44
import '../editor/themes/node_flow_theme.dart';
5+
import 'connection.dart';
56
import 'connection_painter.dart';
67

78
/// Custom painter for rendering all connections in the node flow canvas.
@@ -41,11 +42,13 @@ class ConnectionsCanvas<T> extends CustomPainter {
4142
/// - [store]: The node flow controller containing connection data
4243
/// - [theme]: The visual theme for rendering
4344
/// - [connectionPainter]: Shared painter instance for path caching
45+
/// - [connections]: specific connections to render (defaults to all store.connections)
4446
/// - [animation]: Optional animation for animated connections
4547
const ConnectionsCanvas({
4648
required this.store,
4749
required this.theme,
4850
required this.connectionPainter,
51+
this.connections,
4952
this.animation,
5053
}) : super(repaint: animation);
5154

@@ -61,6 +64,10 @@ class ConnectionsCanvas<T> extends CustomPainter {
6164
/// painting and hit testing, improving performance.
6265
final ConnectionPainter connectionPainter;
6366

67+
/// Specific connections to render.
68+
/// If null, renders all connections from the store.
69+
final List<Connection>? connections;
70+
6471
/// Optional animation for animated connections.
6572
///
6673
/// When provided, the animation value will be passed to animated connections
@@ -81,9 +88,8 @@ class ConnectionsCanvas<T> extends CustomPainter {
8188
// Use the shared cached connection painter
8289
// This ensures paths are cached and reused for both painting and hit testing
8390

84-
// Always use all connections - let InteractiveViewer handle visibility
85-
// This avoids expensive visibility computation during panning
86-
final connectionsToRender = store.connections;
91+
// Use provided list or fallback to all connections
92+
final connectionsToRender = connections ?? store.connections;
8793

8894
// Get current animation value
8995
final animationValue = animation?.value;

packages/vyuh_node_flow/lib/src/editor/controller/connection_api.dart

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,13 @@ extension ConnectionApi<T> on NodeFlowController<T> {
128128
void addConnection(Connection connection) {
129129
runInAction(() {
130130
_connections.add(connection);
131-
// Note: Spatial index is auto-synced via MobX reaction
131+
// Update connection index for O(1) lookup
132+
_connectionsByNodeId
133+
.putIfAbsent(connection.sourceNodeId, () => {})
134+
.add(connection.id);
135+
_connectionsByNodeId
136+
.putIfAbsent(connection.targetNodeId, () => {})
137+
.add(connection.id);
132138
});
133139
// Fire event after successful addition
134140
events.connection?.onCreated?.call(connection);
@@ -151,6 +157,15 @@ extension ConnectionApi<T> on NodeFlowController<T> {
151157
runInAction(() {
152158
_connections.removeWhere((c) => c.id == connectionId);
153159
_selectedConnectionIds.remove(connectionId);
160+
161+
// Update connection index for O(1) lookup
162+
_connectionsByNodeId[connectionToDelete.sourceNodeId]?.remove(
163+
connectionId,
164+
);
165+
_connectionsByNodeId[connectionToDelete.targetNodeId]?.remove(
166+
connectionId,
167+
);
168+
154169
// Remove from spatial index
155170
_spatialIndex.removeConnection(connectionId);
156171
});
@@ -215,6 +230,11 @@ extension ConnectionApi<T> on NodeFlowController<T> {
215230
// Remove from spatial index and path cache
216231
_spatialIndex.removeConnection(conn.id);
217232
_connectionPainter?.removeConnectionFromCache(conn.id);
233+
234+
// Update connection index for O(1) lookup
235+
_connectionsByNodeId[conn.sourceNodeId]?.remove(conn.id);
236+
_connectionsByNodeId[conn.targetNodeId]?.remove(conn.id);
237+
218238
// Remove from connections list
219239
_connections.remove(conn);
220240
}

packages/vyuh_node_flow/lib/src/editor/controller/node_api.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,6 +1045,16 @@ extension NodeApi<T> on NodeFlowController<T> {
10451045
void rebuildAllConnectionSegments() {
10461046
if (!isConnectionPainterInitialized || _theme == null) return;
10471047

1048+
// Use the custom segment calculator if provided during initialization
1049+
// This allows tests and custom implementations to override the default path cache logic
1050+
if (_connectionSegmentCalculator != null) {
1051+
_spatialIndex.rebuildConnectionsWithSegments(
1052+
_connections,
1053+
_connectionSegmentCalculator!,
1054+
);
1055+
return;
1056+
}
1057+
10481058
final pathCache = _connectionPainter!.pathCache;
10491059
final connectionStyle = _theme!.connectionTheme.style;
10501060

0 commit comments

Comments
 (0)