Skip to content

Commit

Permalink
feat: added elkjs layout example
Browse files Browse the repository at this point in the history
  • Loading branch information
siarheihuzarevich committed Aug 15, 2024
1 parent 102a771 commit 9695e08
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 0 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
"@foblex/core": "^1.1.6",
"@foblex/f-docs": "^1.2.2",
"dagre": "^0.8.5",
"elkjs": "^0.9.3",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.3"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<f-flow fDraggable (fLoaded)="onLoaded()">
<f-canvas fZoom>
@for (connection of connections;track connection.id) {
<f-connection [fOffset]="8" [fOutputId]="connection.from" [fInputId]="connection.to" fType="segment"
fBehavior="fixed"></f-connection>
}

@for (node of nodes;track node.id) {
<div fNode [fNodePosition]="node.position"
fDragHandle
fNodeOutput [fOutputId]="node.connectorId"
[fOutputConnectableSide]="configuration.outputSide"
fNodeInput [fInputId]="node.connectorId"
[fInputConnectableSide]="configuration.inputSide">
{{ node.connectorId }}
</div>
}
</f-canvas>
</f-flow>
<div class="toolbar">
<button class="f-button" (click)="horizontal()">Horizontal</button>
<button class="f-button" (click)="vertical()">Vertical</button>
<f-checkbox [checked]="isAutoLayout" (change)="onAutoLayoutChange($event)">Auto Layout
</f-checkbox>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
@use "../flow-common";

::ng-deep elkjs-layout-example {
@include flow-common.connection;
}

.f-node {
@include flow-common.node;
}

.toolbar {
@include flow-common.toolbar;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit, ViewChild } from '@angular/core';
import { EFConnectableSide, FCanvasComponent, FFlowComponent, FFlowModule } from '@foblex/flow';
import ELK from 'elkjs/lib/elk.bundled.js';
import { GuidExtensions, PointExtensions } from '@foblex/core';
import { FCheckboxComponent } from '@foblex/f-docs';

@Component({
selector: 'elkjs-layout-example',
styleUrls: [ './elkjs-layout-example.component.scss' ],
templateUrl: './elkjs-layout-example.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [
FFlowModule,
FCheckboxComponent
]
})
export class ElkjsLayoutExampleComponent implements OnInit {

public nodes: any[] = [];
public connections: any[] = [];

public configuration = CONFIGURATION[ Direction.TOP_TO_BOTTOM ];

@ViewChild(FFlowComponent, { static: true })
public fFlowComponent!: FFlowComponent;

@ViewChild(FCanvasComponent, { static: true })
public fCanvasComponent!: FCanvasComponent;

public isAutoLayout: boolean = true;

constructor(
private changeDetectorRef: ChangeDetectorRef
) {
}

public ngOnInit(): void {
this.getData(Direction.TOP_TO_BOTTOM);
}

public onLoaded(): void {
this.fitToScreen();
}

private getData(direction: Direction): void {
this.configuration = CONFIGURATION[ direction ];
if (this.isAutoLayout) {
this.fFlowComponent.reset();
// if auto layout is disabled, onLoaded will be called only after the first rendering of the flow
}
this.mapGraphData({
id: 'root',
layoutOptions: {
'elk.algorithm': 'layered',
'elk.direction': direction,
},
...GRAPH_DATA
});
}

private async mapGraphData(configuration: any): Promise<void> {
const data = await new ELK().layout(configuration);
this.connections = this.getConnections(data);
this.nodes = this.getNodes(data);
this.changeDetectorRef.markForCheck();
}

private getNodes(data: any): any[] {
return data.children!.map((node: any) => {
return {
id: GuidExtensions.generate(),
connectorId: node.id,
position: PointExtensions.initialize(node.x, node.y)
};
});
}

private getConnections(data: any): any[] {
return data.edges!.map((edge: any) => {
return {
id: GuidExtensions.generate(),
from: edge.sources[ 0 ],
to: edge.targets[ 0 ]
};
});
}

public horizontal(): void {
this.getData(Direction.LEFT_TO_RIGHT);
}

public vertical(): void {
this.getData(Direction.TOP_TO_BOTTOM);
}

public fitToScreen(): void {
this.fCanvasComponent.fitToScreen(PointExtensions.initialize(50, 50), false);
}

public onAutoLayoutChange(checked: boolean): void {
this.isAutoLayout = checked;
}
}

enum Direction {
LEFT_TO_RIGHT = 'RIGHT',
TOP_TO_BOTTOM = 'DOWN'
}

const CONFIGURATION = {
[ Direction.LEFT_TO_RIGHT ]: {
outputSide: EFConnectableSide.RIGHT,
inputSide: EFConnectableSide.LEFT
},
[ Direction.TOP_TO_BOTTOM ]: {
outputSide: EFConnectableSide.BOTTOM,
inputSide: EFConnectableSide.TOP
}
};

const GRAPH_DATA = {
children: [
{ id: 'Node1', width: 100, height: 33 },
{ id: 'Node2', width: 100, height: 33 },
{ id: 'Node3', width: 100, height: 33 },
{ id: 'Node4', width: 100, height: 33 },
{ id: 'Node5', width: 100, height: 33 },
{ id: 'Node6', width: 100, height: 33 },
{ id: 'Node7', width: 100, height: 33 },
{ id: 'Node8', width: 100, height: 33 }
],
edges: [
{ id: 'Edge1', sources: [ 'Node1' ], targets: [ 'Node2' ] },
{ id: 'Edge2', sources: [ 'Node1' ], targets: [ 'Node3' ] },
{ id: 'Edge3', sources: [ 'Node3' ], targets: [ 'Node4' ] },
{ id: 'Edge4', sources: [ 'Node3' ], targets: [ 'Node5' ] },
{ id: 'Edge5', sources: [ 'Node3' ], targets: [ 'Node6' ] },
{ id: 'Edge6', sources: [ 'Node3' ], targets: [ 'Node7' ] },
{ id: 'Edge7', sources: [ 'Node2' ], targets: [ 'Node8' ] }
]
};
15 changes: 15 additions & 0 deletions public/docs/en/elkjs-layout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# ELKJS Tree

## Examples

#### ELKJS Layout Example

Example of a tree layout using the [elkjs](https://github.com/kieler/elkjs) with Foblex Flow to create simple tree layouts.

::: ng-component <elkjs-layout-example></elkjs-layout-example> [height]="600"
[component.html] <<< https://raw.githubusercontent.com/Foblex/f-flow/main/projects/f-examples/elkjs-layout-example/elkjs-layout-example.component.html
[component.ts] <<< https://raw.githubusercontent.com/Foblex/f-flow/main/projects/f-examples/elkjs-layout-example/elkjs-layout-example.component.ts
[component.scss] <<< https://raw.githubusercontent.com/Foblex/f-flow/main/projects/f-examples/elkjs-layout-example/elkjs-layout-example.component.scss
[common.scss] <<< https://raw.githubusercontent.com/Foblex/f-flow/main/projects/f-examples/_flow-common.scss
:::

0 comments on commit 9695e08

Please sign in to comment.