Skip to content

Commit 77673e3

Browse files
author
shuzarevich
committed
feat(flow): add cache, connection worker, virtualization, and zoom during drag
1 parent 2019ea4 commit 77673e3

333 files changed

Lines changed: 4413 additions & 1195 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

projects/f-examples/extensions/minimap-example/minimap-example.component.html

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
11
<f-flow fDraggable (fLoaded)="onLoaded()">
2-
<f-canvas>
3-
<f-connection fOutputId="output1" fInputId="input1" fBehavior="floating"></f-connection>
4-
<div fNode [fNodePosition]="{ x: 24, y: 24 }" fNodeOutput fOutputId="output1" fDragHandle>I'm a node</div>
5-
<div fNode [fNodePosition]="{ x: 244, y: 24 }" fNodeInput fInputId="input1" fDragHandle>I'm a node</div>
6-
<div [fMinimapClass]="['custom-class-for-minimap']" fNode [fNodePosition]="{ x: 244, y: 164 }" fDragHandle>I'm a node</div>
2+
<f-canvas fZoom>
3+
<f-connection fOutputId="output1" fInputId="input1" fBehavior="floating" />
4+
<div fNode [fNodePosition]="{ x: 24, y: 24 }" fNodeOutput fOutputId="output1" fDragHandle>
5+
I'm a node
6+
</div>
7+
<div fNode [fNodePosition]="{ x: 244, y: 24 }" fNodeInput fInputId="input1" fDragHandle>
8+
I'm a node
9+
</div>
10+
<div
11+
[fMinimapClass]="['custom-class-for-minimap']"
12+
fNode
13+
[fNodePosition]="{ x: 244, y: 164 }"
14+
fDragHandle
15+
>
16+
I'm a node
17+
</div>
718
</f-canvas>
819
<div class="any-container-or-without-container">
9-
<f-minimap [fMinSize]="2000"></f-minimap>
20+
<f-minimap [fMinSize]="2000" />
1021
</div>
11-
1222
</f-flow>
13-
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
<f-flow fDraggable (fLoaded)="onLoaded()">
2-
<f-selection-area></f-selection-area>
3-
<f-canvas>
2+
<f-selection-area />
3+
<f-canvas fZoom>
44
<f-connection fOutputId="output1" fInputId="input1" fBehavior="floating"></f-connection>
55
<div fNode [fNodePosition]="{ x: 0, y: 0 }" fDragHandle>
66
<div fNodeOutput fOutputId="output1" class="right"></div>
77
I'm a node
88
</div>
9-
<div fNode [fNodePosition]="{ x: 200, y: 0 }" fDragHandle>
9+
<div fNode [fNodePosition]="{ x: 200, y: 0 }" fDragHandle>
1010
<div fNodeInput fInputId="input1" class="left"></div>
1111
I'm a node
1212
</div>
1313
</f-canvas>
1414
</f-flow>
15-

projects/f-examples/extensions/selection-area/selection-area.component.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,13 @@ import { FCanvasComponent, FFlowModule } from '@foblex/flow';
33

44
@Component({
55
selector: 'selection-area',
6-
styleUrls: [
7-
'./selection-area.component.scss'
8-
],
6+
styleUrls: ['./selection-area.component.scss'],
97
templateUrl: './selection-area.component.html',
108
changeDetection: ChangeDetectionStrategy.OnPush,
119
standalone: true,
12-
imports: [
13-
FFlowModule
14-
]
10+
imports: [FFlowModule],
1511
})
1612
export class SelectionAreaComponent {
17-
1813
@ViewChild(FCanvasComponent, { static: true })
1914
public fCanvas!: FCanvasComponent;
2015

projects/f-examples/nodes/custom-nodes/custom-nodes.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export class CustomNodesComponent implements OnDestroy {
2828
private readonly _browser = inject(BrowserService);
2929

3030
protected loaded(): void {
31-
this._canvas()?.fitToScreen(PointExtensions.initialize(100, 100), false);
31+
this._canvas()?.fitToScreen(PointExtensions.initialize(100, 100), true);
3232
}
3333

3434
protected onCanvasChanged(event: FCanvasChangeEvent): void {

projects/f-examples/nodes/drag-handle/drag-handle.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,25 @@ export class DragHandle {
1818
* Resets the canvas scale and centers the view without animation.
1919
*/
2020
protected loaded(): void {
21-
this._canvas()?.resetScaleAndCenter(false);
21+
this._canvas()?.resetScaleAndCenter(true);
2222
}
2323

2424
/**
2525
* Called when one or more nodes are moved.
2626
* Can be used to track movements or persist state.
2727
*
28-
* @param event - Node movement event containing affected nodes and delta.
28+
* @param _event - Node movement event containing affected nodes and delta.
2929
*/
30-
protected moveNodes(event: FMoveNodesEvent): void {
30+
protected moveNodes(_event: FMoveNodesEvent): void {
3131
// Handle node movement.
3232
}
3333

3434
/**
3535
* Called when a single node's position changes.
3636
*
37-
* @param position - The new position of the node.
37+
* @param _position - The new position of the node.
3838
*/
39-
protected positionChanged(position: IPoint): void {
39+
protected positionChanged(_position: IPoint): void {
4040
// Handle node position change.
4141
}
4242
}
Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,17 @@
11
import { ChangeDetectionStrategy, Component, viewChild } from '@angular/core';
2-
import {
3-
EFResizeHandleType,
4-
FCanvasComponent,
5-
FFlowModule
6-
} from '@foblex/flow';
2+
import { EFResizeHandleType, FCanvasComponent, FFlowModule } from '@foblex/flow';
73
import { IRect } from '@foblex/2d';
84
import { MatIcon } from '@angular/material/icon';
95

106
@Component({
117
selector: 'resize-handle',
12-
styleUrls: [ './resize-handle.component.scss' ],
8+
styleUrls: ['./resize-handle.component.scss'],
139
templateUrl: './resize-handle.component.html',
1410
changeDetection: ChangeDetectionStrategy.OnPush,
1511
standalone: true,
16-
imports: [
17-
FFlowModule,
18-
MatIcon,
19-
]
12+
imports: [FFlowModule, MatIcon],
2013
})
2114
export class ResizeHandleComponent {
22-
2315
private _fCanvas = viewChild.required(FCanvasComponent);
2416

2517
protected readonly eResizeHandleType = EFResizeHandleType;
@@ -28,7 +20,7 @@ export class ResizeHandleComponent {
2820
this._fCanvas().resetScaleAndCenter(false);
2921
}
3022

31-
protected onNodeSizeChanged(rect: IRect): void {
23+
protected onNodeSizeChanged(_rect: IRect): void {
3224
//process data
3325
}
3426
}

projects/f-examples/nodes/stress-test/stress-test.component.html

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,39 @@
1-
@if (columns()) {
2-
<f-flow fDraggable (fLoaded)="loaded()">
1+
@if (cells()) {
2+
<f-flow fDraggable (fLoaded)="loaded()" [fCache]="cache()">
3+
<f-selection-area />
4+
35
<f-canvas fZoom>
4-
<ng-container ngProjectAs="[fNodes]">
5-
@for (column of columns(); track column; let cIndex = $index) {
6-
@for (node of column; track node; let rIndex = $index) {
6+
@if (virtualization()) {
7+
<ng-container ngProjectAs="[fNodes]" *fVirtualFor="let cell of cells(); trackBy trackCell;">
8+
<div
9+
fNode
10+
[fNodePosition]="{ x: 120 * cell.cIndex, y: cell.rIndex * 120 }"
11+
fDragHandle
12+
fNodeInput
13+
[fInputId]="cell.node"
14+
fNodeOutput
15+
[fOutputId]="cell.node"
16+
>
17+
Node
18+
</div>
19+
</ng-container>
20+
} @else {
21+
<ng-container ngProjectAs="[fNodes]">
22+
@for (cell of cells(); track $index) {
723
<div
824
fNode
9-
[fNodePosition]="{ x: 120 * cIndex, y: rIndex * 120 }"
25+
[fNodePosition]="{ x: 120 * cell.cIndex, y: cell.rIndex * 120 }"
1026
fDragHandle
1127
fNodeInput
12-
[fInputId]="node"
28+
[fInputId]="cell.node"
1329
fNodeOutput
14-
[fOutputId]="node"
30+
[fOutputId]="cell.node"
1531
>
1632
Node
1733
</div>
1834
}
19-
}
20-
</ng-container>
35+
</ng-container>
36+
}
2137

2238
<ng-container ngProjectAs="[fConnections]">
2339
@if (showConnections()) {
@@ -36,6 +52,10 @@
3652
</f-canvas>
3753
</f-flow>
3854
<div class="examples-toolbar">
55+
<f-checkbox [checked]="cache()" (change)="toggleCache()">Cache</f-checkbox>
56+
<f-checkbox [checked]="virtualization()" (change)="toggleVirtualization()"
57+
>Virtualization</f-checkbox
58+
>
3959
<f-checkbox [checked]="showConnections()" (change)="toggleConnections()"
4060
>Show Connections</f-checkbox
4161
>

projects/f-examples/nodes/stress-test/stress-test.component.scss

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,17 @@
44
@include flow-common.connection;
55
}
66

7+
.f-selection-area {
8+
background-color: var(--selection-area-color);
9+
}
10+
711
.f-node {
812
@include flow-common.node;
913
width: unset;
14+
15+
&.f-selected {
16+
border: 1px solid var(--node-selected-border-color);
17+
}
1018
}
1119

1220
@include flow-common.examples-toolbar;

projects/f-examples/nodes/stress-test/stress-test.component.ts

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {
77
viewChild,
88
} from '@angular/core';
99
import { FCanvasComponent, FFlowComponent, FFlowModule, FZoomDirective } from '@foblex/flow';
10-
import { NgForOf } from '@angular/common';
1110
import { PointExtensions } from '@foblex/2d';
1211
import { MatFormField, MatLabel } from '@angular/material/form-field';
1312
import { MatOption } from '@angular/material/core';
@@ -16,6 +15,12 @@ import { FCheckboxComponent } from '@foblex/m-render';
1615

1716
type Edge = { source: number; target: number };
1817

18+
type Cell = {
19+
node: number;
20+
cIndex: number;
21+
rIndex: number;
22+
};
23+
1924
@Component({
2025
selector: 'stress-test',
2126
styleUrls: ['./stress-test.component.scss'],
@@ -24,7 +29,6 @@ type Edge = { source: number; target: number };
2429
standalone: true,
2530
imports: [
2631
FFlowModule,
27-
NgForOf,
2832
FZoomDirective,
2933
MatFormField,
3034
MatLabel,
@@ -37,23 +41,37 @@ export class StressTestComponent {
3741
private readonly _canvas = viewChild.required(FCanvasComponent);
3842
private readonly _flow = viewChild(FFlowComponent);
3943

40-
protected readonly totals = [200, 500, 1000, 2000];
44+
protected readonly totals = [200, 500, 1000, 2000, 5000];
4145

4246
protected readonly showConnections = signal(false);
47+
protected readonly virtualization = signal(false);
48+
protected readonly cache = signal(false);
49+
4350
protected readonly totalNodes = signal(200);
44-
protected readonly columns = computed(() => {
51+
52+
protected readonly cells = computed<readonly Cell[]>(() => {
4553
const total = this.totalNodes();
54+
4655
const cols = Math.ceil(Math.sqrt(total));
4756
const nodesPerCol = Math.ceil(total / cols);
4857

4958
untracked(() => this._flow()?.reset());
50-
const numbers = Array.from({ length: total }, (_, i) => i + 1);
5159

52-
return Array.from({ length: cols }, (_, i) =>
53-
numbers.slice(i * nodesPerCol, (i + 1) * nodesPerCol),
54-
);
60+
const result: Cell[] = new Array(total);
61+
62+
for (let i = 0; i < total; i++) {
63+
const node = i + 1;
64+
const cIndex = Math.floor(i / nodesPerCol);
65+
const rIndex = i - cIndex * nodesPerCol;
66+
67+
result[i] = { node, cIndex, rIndex };
68+
}
69+
70+
return result;
5571
});
5672

73+
protected readonly trackCell = (_: number, c: Cell) => c.cIndex + '-' + c.rIndex;
74+
5775
protected readonly connections = computed<Edge[]>(() => {
5876
const total = this.totalNodes();
5977
const edges: Edge[] = [];
@@ -71,4 +89,13 @@ export class StressTestComponent {
7189
protected toggleConnections(): void {
7290
this.showConnections.update((x) => !x);
7391
}
92+
93+
protected toggleVirtualization(): void {
94+
this._flow()?.reset();
95+
this.virtualization.update((x) => !x);
96+
}
97+
98+
protected toggleCache(): void {
99+
this.cache.update((x) => !x);
100+
}
74101
}

projects/f-flow/src/domain/drag-rect-cache.ts

Lines changed: 0 additions & 24 deletions
This file was deleted.

0 commit comments

Comments
 (0)