Skip to content

Commit

Permalink
feat: added dagre layout example
Browse files Browse the repository at this point in the history
  • Loading branch information
siarheihuzarevich committed Aug 12, 2024
1 parent 036e192 commit 737dd1f
Show file tree
Hide file tree
Showing 6 changed files with 239 additions and 5 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"@angular/router": "^18.1.0",
"@foblex/core": "^1.1.6",
"@foblex/f-docs": "^1.2.1",
"dagre": "^0.8.5",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.3"
Expand All @@ -68,6 +69,7 @@
"@angular-devkit/build-angular": "^18.1.2",
"@angular/cli": "^18.1.2",
"@angular/compiler-cli": "^18.1.0",
"@types/dagre": "^0.7.52",
"@types/jasmine": "~5.1.0",
"jasmine-core": "~5.1.0",
"karma": "~6.4.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<f-flow fDraggable>
<f-canvas>
@for (connection of connections;track connection.from) {
<f-connection [fOffset]="8" [fOutputId]="connection.from" [fInputId]="connection.to" fType="segment" fBehavior="fixed"></f-connection>
}

@for (node of nodes;track node.position) {
<div fNode [fNodePosition]="node.position"
fDragHandle
fNodeOutput [fOutputId]="node.id"
[fOutputConnectableSide]="configuration.outputSide"
fNodeInput [fInputId]="node.id"
[fInputConnectableSide]="configuration.inputSide">
{{ node.id }}
</div>
}
</f-canvas>
</f-flow>
<div class="toolbar">
<button (click)="horizontal()">Horizontal</button>
<button (click)="vertical()">Vertical</button>
<button (click)="fitToScreen()">Fit to Screen</button>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
:host ::ng-deep {

.f-connection {
.f-connection-drag-handle {
fill: transparent;
}

.f-connection-selection {
fill: none;
}

.f-connection-path {
fill: none;
stroke: #585858;
stroke-width: 2;
}
}
}

.f-node {
width: 100px;
padding: 12px;
color: #585858;
display: inline-flex;
justify-content: center;
align-items: center;
text-align: center;
background: #FCFDFE;
border-radius: 4px;
box-shadow: 0 0 1px 1px #E4E3E6;
}

.toolbar {
display: flex;
justify-content: flex-end;
align-items: center;
flex-wrap: wrap;
gap: 8px;
position: absolute;
right: 16px;
top: 16px;
}

button {
display: inline-block;
text-align: center;
font-weight: 500;
white-space: nowrap;
border: none;
border-radius: 2px;
padding: 4px 8px;
font-size: 14px;

color: var(--button-default-text);
background-color: var(--button-default-bg);
cursor: pointer;

&:hover {
color: var(--button-default-hover-text);
background-color: var(--button-default-hover-bg);
}

&:active {
color: var(--button-default-active-text);
background-color: var(--button-default-active-bg);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { ChangeDetectionStrategy, Component, OnInit, ViewChild } from '@angular/core';
import { EFConnectableSide, FCanvasComponent, FFlowModule } from '@foblex/flow';
import * as dagre from "dagre";
import { IPoint, PointExtensions } from '@foblex/core';
import { graphlib } from 'dagre';
import Graph = graphlib.Graph;

interface INodeViewModel {
id: string;
position: IPoint;
}

interface IConnectionViewModel {
from: string;
to: string;
}

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

public nodes: INodeViewModel[] = [];
public connections: IConnectionViewModel[] = [];

public configuration = CONFIGURATION[ Direction.LEFT_TO_RIGHT ];

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

public ngOnInit(): void {
this.getData(new dagre.graphlib.Graph(), Direction.LEFT_TO_RIGHT);
}

private getData(graph: Graph, direction: Direction): void {
this.setGraph(graph, direction);
this.nodes = this.getNodes(graph);
this.connections = this.getConnections(graph);
}

private setGraph(graph: Graph, direction: Direction): void {
this.configuration = CONFIGURATION[ direction ];
graph.setGraph({ rankdir: direction });
GRAPH_DATA.forEach(node => {
graph.setNode(node.id, { width: 100, height: 48 });
if (node.parentId != null) {
graph.setEdge(node.parentId, node.id, {});
}
});
dagre.layout(graph);
}

private getNodes(graph: Graph): INodeViewModel[] {
return graph.nodes().map((x) => {
let node = graph.node(x);
return {
id: x, position: { x: node.x, y: node.y }
}
});
}

private getConnections(graph: Graph): IConnectionViewModel[] {
return graph.edges().map((x) => ({ from: x.v, to: x.w }));
}

public horizontal(): void {
this.getData(new dagre.graphlib.Graph(), Direction.LEFT_TO_RIGHT);
}

public vertical(): void {
this.getData(new dagre.graphlib.Graph(), Direction.TOP_TO_BOTTOM);
}

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

enum Direction {
LEFT_TO_RIGHT = 'LR',
TOP_TO_BOTTOM = 'TB'
}

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 = [
{ id: 'Node1', parentId: null },
{ id: 'Node2', parentId: 'Node1' },
{ id: 'Node3', parentId: 'Node1' },
{ id: 'Node4', parentId: 'Node3' },
{ id: 'Node5', parentId: 'Node3' },
{ id: 'Node6', parentId: 'Node3' },
{ id: 'Node7', parentId: 'Node3' },
{ id: 'Node8', parentId: 'Node2' }
];
27 changes: 22 additions & 5 deletions public/docs/en/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ import {
import {
MinimapScaledExampleComponent
} from '../../../projects/f-examples/minimap-scaled-example/minimap-scaled-example.component';
import {
DagreLayoutExampleComponent
} from '../../../projects/f-examples/dagre-layout-example/dagre-layout-example.component';

export const ENGLISH_ENVIRONMENT: IDocsEnvironment = createEnvironment();

Expand All @@ -50,7 +53,8 @@ function createEnvironment(): IDocsEnvironment {
connectorGroup(),
connectionGroup(),
extendsGroup(),
proExamplesGroup()
layoutGroup(),
proExamplesGroup(),
],
footerNavigation: {
editLink: {
Expand All @@ -77,12 +81,13 @@ function createEnvironment(): IDocsEnvironment {
{ tag: 'visual-programming-flow', component: FlowComponent },
{ tag: 'minimap-basic-example', component: MinimapBasicExampleComponent },
{ tag: 'minimap-scaled-example', component: MinimapScaledExampleComponent },
{ tag: 'dagre-layout-example', component: DagreLayoutExampleComponent }
],
socialLinks: [
{ icon: 'github', link: 'https://github.com/Foblex/f-flow' },
{ icon: 'npm', link: 'https://www.npmjs.com/package/@foblex/flow' },
],
toC:{
toC: {
title: 'In this article',
range: { start: 2, end: 6 },
}
Expand Down Expand Up @@ -197,10 +202,22 @@ function extendsGroup(): INavigationGroup {
}
}

function layoutGroup(): INavigationGroup {
return {
text: 'Layouts & Behaviors',
items: [
{
link: 'f-dagre-layout',
text: 'Dagre Tree',
}
],
}
}

function proExamplesGroup(): INavigationGroup {
return {
return {
text: 'Pro Examples',
items: [{
items: [ {
text: 'Visual Programming Flow',
link: 'f-visual-programming-flow',
}, {
Expand All @@ -209,7 +226,7 @@ function proExamplesGroup(): INavigationGroup {
}, {
text: 'Scheme Editor',
link: 'https://github.com/Foblex/f-scheme-editor',
}]
} ]
}
}

14 changes: 14 additions & 0 deletions public/docs/en/f-dagre-layout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Dagre Tree

## Examples

#### Dagre Layout Example

Example of a tree layout using the dagre.js with Foblex Flow to create simple tree layouts.

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

0 comments on commit 737dd1f

Please sign in to comment.