diff --git a/hugo/assets/scripts/domainmodel/d3tree.tsx b/hugo/assets/scripts/domainmodel/d3tree.tsx index ade317a3..bbc7e442 100644 --- a/hugo/assets/scripts/domainmodel/d3tree.tsx +++ b/hugo/assets/scripts/domainmodel/d3tree.tsx @@ -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(); @@ -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') diff --git a/hugo/assets/scripts/domainmodel/domainmodel-tools.ts b/hugo/assets/scripts/domainmodel/domainmodel-tools.ts index 30052e19..c174eb44 100644 --- a/hugo/assets/scripts/domainmodel/domainmodel-tools.ts +++ b/hugo/assets/scripts/domainmodel/domainmodel-tools.ts @@ -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 { @@ -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 => { + 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 => { @@ -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 { @@ -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 { diff --git a/hugo/assets/scripts/domainmodel/domainmodel.tsx b/hugo/assets/scripts/domainmodel/domainmodel.tsx index 0a3e3d89..c07a4ab4 100644 --- a/hugo/assets/scripts/domainmodel/domainmodel.tsx +++ b/hugo/assets/scripts/domainmodel/domainmodel.tsx @@ -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'); @@ -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 ( - + ); } diff --git a/package-lock.json b/package-lock.json index c89c8563..155d8ee0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ } }, "core": { + "name": "langium-website-core", "version": "1.0.0", "license": "MIT", "dependencies": {