Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minor DomainModel Showcase fixes #200

Merged
merged 8 commits into from
Oct 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 16 additions & 16 deletions hugo/assets/scripts/domainmodel/d3tree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,22 @@ export default function D3Tree({ data }: TreeProps) {
useEffect(() => {
if (!svgRef.current) return;

// get the size of the tree
const getChildSize = (child: TreeNode): number => {
// get the leaf nodes of the tree
const getLeafNodes = (child: TreeNode): number => {
if (!child.children) return 1;
let amount = child.children.length;

// fastest way to iterate over an array
const length = child.children.length;
for (let i = 0; i < length; i++) {
amount += getChildSize(child.children[i]);
}
return amount;
if(child.children.length === 0) return 1;
return child.children.map(getLeafNodes).reduce((a, b) => a + b);
};

const size = getChildSize(data);
const height = size * 20;
const width = size * 18;
// get the longest path in the tree
const getLongestPath = (child: TreeNode): number => {
if (!child.children) return 1;
if(child.children.length === 0) return 1;
return 1 + Math.max(...child.children.map(getLongestPath));
};

const height = getLeafNodes(data) * 60;
const width = getLongestPath(data) * 120;

const svg = d3.select(svgRef.current);
svg.selectAll('*').remove();
Expand All @@ -51,10 +51,10 @@ export default function D3Tree({ data }: TreeProps) {
g.attr('transform', event.transform);
});

svg.call(zoom, d3.zoomIdentity.translate(50, 50));

// zoom to show the whole tree
svg.call(zoom.transform, d3.zoomIdentity.translate(width / size * 3, height / size * 2).scale(3 / (0.1 * size)));
svg.call(zoom.transform, d3.zoomIdentity.translate(width / 20, height / 30).scale(0.5));

svg.call(zoom, d3.zoomIdentity.translate(50, 50));

// draw the links
g.selectAll('.link')
Expand Down
59 changes: 40 additions & 19 deletions hugo/assets/scripts/domainmodel/domainmodel-tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,8 @@ import { AstNode } from "../langium-utils/langium-ast";
import { TreeNode } from "./d3tree";


export function getTreeNode(ast: AstNode): TreeNode {
export function getMainTreeNode(ast: AstNode): TreeNode {
const astNode = getDomainModelAst(ast as DomainModelAstNode);

// create a TreeNode from all PackageDeclarations in the ast
const packageDeclarations = astNode.packageDeclarations.map(p => {
return {
...p,
children: p.elements
} as TreeNode;
});

// create a TreeNode a DataType
const getDataTypeTreeNode = (d: DataType): TreeNode => {
return {
Expand All @@ -22,6 +13,24 @@ export function getTreeNode(ast: AstNode): TreeNode {
}
}

// create a TreeNode from a PackageDeclaration
const getPackageDeclarationTreeNode = (p: PackageDeclaration): TreeNode => {
return {
...p,
children: p.elements.map(e => getTreeNode(e))
}
}

// create a TreeNode from any DomainModelElement
const getTreeNode = (e: DomainModelElement): TreeNode => {
emilkrebs marked this conversation as resolved.
Show resolved Hide resolved
switch(e.$type) {
case 'DataType': return getDataTypeTreeNode(e as DataType);
case 'Entity': return getEntityTreeNode(e as Entity);
case 'PackageDeclaration': return getPackageDeclarationTreeNode(e as PackageDeclaration);
default: return e as TreeNode;
}
}

// create a TreeNode from an Entity
const getEntityTreeNode = (entity: Entity): TreeNode => {

Expand Down Expand Up @@ -58,16 +67,28 @@ export function getTreeNode(ast: AstNode): TreeNode {

// create a TreeNode from all Entities in the ast
const entities = astNode.entities.flatMap(e => getEntityTreeNode(e));

// create a TreeNode from all DataTypes in the ast
const datatypes = astNode.dataTypes.map(d => getDataTypeTreeNode(d));

// combine them all to a single TreeNode
const children: TreeNode[] = [
{name: 'DataTypes', $type: 'DataType', children: datatypes},
{name: 'Entities', $type: 'Entity', children: entities},
{name: 'Packages', $type: 'PackageDeclaration', children: packageDeclarations},
];
// create a TreeNode from all PackageDeclarations in the ast
const packageDeclarations = astNode.packageDeclarations.map(p => getPackageDeclarationTreeNode(p));

const children: TreeNode[] = [];

// if datatypes exist, add them to the children
if(datatypes.length > 0) {
children.push({ name: 'DataTypes', $type: 'DataType', children: datatypes });
}

// if entities exist, add them to the children
if(entities.length > 0) {
children.push({name: 'Entities', $type: 'Entity', children: entities});
}

// if packageDeclarations exist, add them to the children
if(packageDeclarations.length > 0) {
children.push({name: 'Packages', $type: 'PackageDeclaration', children: packageDeclarations});
}


// return the root TreeNode
return {
Expand Down Expand Up @@ -103,7 +124,7 @@ export interface DomainModelAstNode extends AstNode, DomainModelElement {

export interface PackageDeclaration extends DomainModelElement {
$type: 'PackageDeclaration';
elements: DataType[];
elements: DomainModelElementType[];
}

export interface Entity extends DomainModelElement {
Expand Down
5 changes: 3 additions & 2 deletions hugo/assets/scripts/domainmodel/domainmodel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { buildWorkerDefinition } from "monaco-editor-workers";
import React from "react";
import { createRoot } from "react-dom/client";
import { Diagnostic, DocumentChangeResponse, LangiumAST } from "../langium-utils/langium-ast";
import { DomainModelAstNode, example, getTreeNode, syntaxHighlighting } from "./domainmodel-tools";
import { DomainModelAstNode, example, getMainTreeNode, syntaxHighlighting } from "./domainmodel-tools";

import D3Tree from "./d3tree";

addMonacoStyles('monaco-styles-helper');
Expand Down Expand Up @@ -85,7 +86,7 @@ class App extends React.Component<{}, AppState> {
// if there are no errors, render the tree
if (this.state.diagnostics == null || this.state.diagnostics.filter((i) => i.severity === 1).length == 0) {
return (
<D3Tree data={getTreeNode(ast)} />
<D3Tree data={getMainTreeNode(ast)} />
);
}

Expand Down
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading