This commit is contained in:
Knut Sveidqvist
2024-01-30 16:05:16 +01:00
parent 4a04ce6bf8
commit df9b801b0e
8 changed files with 64 additions and 196 deletions

View File

@@ -65,7 +65,7 @@
<body>
<pre id="diagram" class="mermaid">
block-beta
blockArrowId<["Label"]>(right)
blockArrowId<["`Label`"]>(right)
blockArrowId2<["Label"]>(left)
blockArrowId3<["Label"]>(up)
blockArrowId4<["Label"]>(down)

View File

@@ -1,5 +1,5 @@
import type { DiagramDB } from '../../diagram-api/types.js';
import type { BlockConfig, BlockType, Block, Link, ClassDef } from './blockTypes.js';
import type { BlockConfig, BlockType, Block, ClassDef } from './blockTypes.js';
import * as configApi from '../../config.js';
import { clear as commonClear } from '../common/commonDb.js';
import { log } from '../../logger.js';
@@ -240,11 +240,6 @@ const setHierarchy = (block: Block[]): void => {
blocks = rootBlock.children;
};
const addLink = (link: Link): Link => {
links.push(link);
return link;
};
const getColumns = (blockid: string): number => {
const block = blockDatabase[blockid];
if (!block) {
@@ -264,13 +259,6 @@ const getColumns = (blockid: string): number => {
* @returns
*/
const getBlocksFlat = () => {
// const result: Block[] = [];
// // log.debug('abc88 getBlocksFlat', blockDatabase);
// const keys = Object.keys(blockDatabase);
// for (const key of keys) {
// result.push(blockDatabase[key]);
// }
// return result;
return [...Object.values(blockDatabase)];
};
/**
@@ -292,11 +280,8 @@ const setBlock = (block: Block) => {
blockDatabase[block.id] = block;
};
const getLinks = () => links;
const getLogger = () => console;
// type IGetClasses = () => Record<string, ClassDef>;
/**
* Return all of the style classes
*/
@@ -306,15 +291,13 @@ export const getClasses = function () {
const db = {
getConfig: () => configApi.getConfig().block,
addLink: addLink,
typeStr2Type: typeStr2Type,
edgeTypeStr2Type: edgeTypeStr2Type,
edgeStrToEdgeData,
getLogger, // TODO: remove
getLogger,
getBlocksFlat,
getBlocks,
getEdges,
getLinks,
setHierarchy,
getBlock,
setBlock,

View File

@@ -2,19 +2,17 @@ import type { Diagram } from '../../Diagram.js';
import * as configApi from '../../config.js';
import { calculateBlockSizes, insertBlocks, insertEdges } from './renderHelpers.js';
import { layout } from './layout.js';
import { setupGraphViewbox } from '../../setupGraphViewbox.js';
import type { MermaidConfig, BaseDiagramConfig } from '../../config.type.js';
import insertMarkers from '../../dagre-wrapper/markers.js';
import {
select as d3select,
scaleOrdinal as d3scaleOrdinal,
schemeTableau10 as d3schemeTableau10,
} from 'd3';
import type { ContainerElement } from 'd3';
import { log } from '../../logger.js';
import type { BlockDB } from './blockDB.js';
import type { Block } from './blockTypes.js';
// import { diagram as BlockDiagram } from './blockDiagram.js';
import { configureSvgSize } from '../../setupGraphViewbox.js';
/**
@@ -34,7 +32,7 @@ export const draw = async function (
_version: string,
diagObj: Diagram
): Promise<void> {
const { securityLevel, flowchart: conf } = configApi.getConfig();
const { securityLevel, block: conf } = configApi.getConfig();
const db = diagObj.db as BlockDB;
let sandboxElement: any;
if (securityLevel === 'sandbox') {
@@ -65,7 +63,6 @@ export const draw = async function (
const nodes = svg.insert('g').attr('class', 'block');
await calculateBlockSizes(nodes, bl, db);
const bounds = layout(db);
// log.debug('Here be blocks', bl);
await insertBlocks(nodes, bl, db);
await insertEdges(nodes, edges, blArr, db, id);
@@ -80,32 +77,14 @@ export const draw = async function (
const magicFactor = Math.max(1, Math.round(0.125 * (bounds2.width / bounds2.height)));
const height = bounds2.height + magicFactor + 10;
const width = bounds2.width + 10;
const useMaxWidth = false;
configureSvgSize(svg, height, width, useMaxWidth);
const { useMaxWidth } = conf as Exclude<MermaidConfig['block'], undefined>;
configureSvgSize(svg, height, width, !!useMaxWidth);
log.debug('Here Bounds', bounds, bounds2);
svg.attr(
'viewBox',
`${bounds2.x - 5} ${bounds2.y - 5} ${bounds2.width + 10} ${bounds2.height + 10}`
);
}
// svg.attr('viewBox', `${-200} ${-200} ${400} ${400}`);
// Prepare data for construction based on diagObj.db
// This must be a mutable object with `nodes` and `links` properties:
//
// @ts-ignore TODO: db type
// const graph = diagObj.db.getGraph();
// const nodeWidth = 10;
// Create rectangles for nodes
// const db:BlockDB = diagObj.db;
interface LayedBlock extends Block {
children?: LayedBlock[];
x?: number;
y?: number;
}
// Get color scheme for the graph
const colorScheme = d3scaleOrdinal(d3schemeTableau10);

View File

@@ -56,12 +56,7 @@ export interface Block {
styleClass?: string;
styles?: string[];
stylesStr?: string;
w?: number;
}
export interface Link {
source: Block;
target: Block;
widthInColumns?: number;
}
export interface ClassDef {

View File

@@ -1,7 +1,8 @@
import type { BlockDB } from './blockDB.js';
import type { Block } from './blockTypes.js';
import { log } from '../../logger.js';
const padding = 8;
import { getConfig } from '../../diagram-api/diagramAPI.js';
const padding = getConfig()?.block?.padding || 8;
interface BlockPosition {
px: number;
@@ -59,7 +60,7 @@ const getMaxChildSize = (block: Block) => {
continue;
}
if (width > maxWidth) {
maxWidth = width / (block.w || 1);
maxWidth = width / (block.widthInColumns || 1);
}
if (height > maxHeight) {
maxHeight = height;
@@ -68,7 +69,7 @@ const getMaxChildSize = (block: Block) => {
return { width: maxWidth, height: maxHeight };
};
function setBlockSizes(block: Block, db: BlockDB, sieblingWidth = 0, sieblingHeight = 0) {
function setBlockSizes(block: Block, db: BlockDB, siblingWidth = 0, siblingHeight = 0) {
log.debug(
'setBlockSizes abc95 (start)',
block.id,
@@ -76,18 +77,16 @@ function setBlockSizes(block: Block, db: BlockDB, sieblingWidth = 0, sieblingHei
'block width =',
block?.size,
'sieblingWidth',
sieblingWidth
siblingWidth
);
if (!block?.size?.width) {
block.size = {
width: sieblingWidth,
height: sieblingHeight,
width: siblingWidth,
height: siblingHeight,
x: 0,
y: 0,
};
}
const totalWidth = 0;
const totalHeight = 0;
let maxWidth = 0;
let maxHeight = 0;
@@ -105,34 +104,21 @@ function setBlockSizes(block: Block, db: BlockDB, sieblingWidth = 0, sieblingHei
for (const child of block.children) {
if (child.size) {
log.debug(
'abc95 Setting size of children of',
block.id,
'id=',
child.id,
maxWidth,
maxHeight,
child.size
`abc95 Setting size of children of ${block.id} id=${child.id} ${maxWidth} ${maxHeight} ${child.size}`
);
child.size.width = maxWidth * (child.w || 1) + padding * ((child.w || 1) - 1);
child.size.width =
maxWidth * (child.widthInColumns || 1) + padding * ((child.widthInColumns || 1) - 1);
child.size.height = maxHeight;
child.size.x = 0;
child.size.y = 0;
log.debug(
'abc95 updating size of ',
block.id,
' children child:',
child.id,
'maxWidth:',
maxWidth,
'maxHeight:',
maxHeight
`abc95 updating size of ${block.id} children child:${child.id} maxWidth:${maxWidth} maxHeight:${maxHeight}`
);
}
}
for (const child of block.children) {
// log.debug('abc95 fin 2 Setting size', child.id, maxWidth, maxHeight, child.size);
setBlockSizes(child, db, maxWidth, maxHeight);
// log.debug('abc95 fin 3 Setting size', child.id, maxWidth, maxHeight, child.size);
}
const columns = block.columns || -1;
@@ -144,28 +130,21 @@ function setBlockSizes(block: Block, db: BlockDB, sieblingWidth = 0, sieblingHei
xSize = columns;
}
const w = block.w || 1;
const w = block.widthInColumns || 1;
const ySize = Math.ceil(numItems / xSize);
let width = xSize * (maxWidth + padding) + padding;
let height = ySize * (maxHeight + padding) + padding;
// If maxWidth
if (width < sieblingWidth) {
if (width < siblingWidth) {
log.debug(
'Detected to small siebling: abc95',
block.id,
'sieblingWidth',
sieblingWidth,
'sieblingHeight',
sieblingHeight,
'width',
width
`Detected to small siebling: abc95 ${block.id} sieblingWidth ${siblingWidth} sieblingHeight ${siblingHeight} width ${width}`
);
width = sieblingWidth;
height = sieblingHeight;
const childWidth = (sieblingWidth - xSize * padding - padding) / xSize;
const childHeight = (sieblingHeight - ySize * padding - padding) / ySize;
width = siblingWidth;
height = siblingHeight;
const childWidth = (siblingWidth - xSize * padding - padding) / xSize;
const childHeight = (siblingHeight - ySize * padding - padding) / ySize;
log.debug('Size indata abc88', block.id, 'childWidth', childWidth, 'maxWidth', maxWidth);
log.debug('Size indata abc88', block.id, 'childHeight', childHeight, 'maxHeight', maxHeight);
log.debug('Size indata abc88 xSize', xSize, 'paddiong', padding);
@@ -182,17 +161,9 @@ function setBlockSizes(block: Block, db: BlockDB, sieblingWidth = 0, sieblingHei
}
log.debug(
'abc95 (finale calc)',
block.id,
'xSize',
xSize,
'ySize',
ySize,
'columns',
columns,
block.children.length,
'width=',
Math.max(width, block.size?.width || 0)
`abc95 (finale calc) ${block.id} xSize ${xSize} ySize ${ySize} columns ${columns}${
block.children.length
} width=${Math.max(width, block.size?.width || 0)}`
);
if (width < (block?.size?.width || 0)) {
width = block?.size?.width || 0;
@@ -229,14 +200,7 @@ function setBlockSizes(block: Block, db: BlockDB, sieblingWidth = 0, sieblingHei
function layoutBlocks(block: Block, db: BlockDB) {
log.debug(
'abc85 layout blocks (=>layoutBlocks)',
block.id,
'x:',
block?.size?.x,
'y:',
block?.size?.y,
'width:',
block?.size?.width
`abc85 layout blocks (=>layoutBlocks) ${block.id} x: ${block?.size?.x} y: ${block?.size?.y} width: ${block?.size?.width}`
);
const columns = block.columns || -1;
log.debug('layoutBlocks columns abc95', block.id, '=>', columns, block);
@@ -268,56 +232,22 @@ function layoutBlocks(block: Block, db: BlockDB) {
log.debug('New row in layout for block', block.id, ' and child ', child.id, rowPos);
}
log.debug(
'abc89 layout blocks (child) id:',
child.id,
'Pos:',
columnPos,
' (px, py)',
px,
py,
' (',
parent?.size?.x,
',',
parent?.size?.y,
')',
'parent:',
parent.id,
'width:',
width,
padding
`abc89 layout blocks (child) id: ${child.id} Pos: ${columnPos} (px, py) ${px},${py} (${parent?.size?.x},${parent?.size?.y}) parent: ${parent.id} width: ${width}${padding}`
);
if (parent.size) {
// child.size.x =
// block.size.x -
// block.size.width / 2 +
// px * (child?.w || 1) * (width + padding) +
// width / 2 +
// padding;
const halfWidth = width / 2;
child.size.x = startingPosX + padding + halfWidth;
log.debug(
'abc91 layout blocks (calc) px, py',
'id:',
child.id,
'startingPosX',
startingPosX,
'new startingPosX',
child.size.x + halfWidth,
'padding',
padding,
'width=',
width,
'halfWidth',
halfWidth,
'=>',
'x:',
child.size.x,
'y:',
child.size.y,
child.w,
'(width * (child?.w || 1)) / 2',
(width * (child?.w || 1)) / 2
`abc91 layout blocks (calc) px, pyid:${
child.id
} startingPos=X${startingPosX} new startingPosX${
child.size.x
} ${halfWidth} padding=${padding} width=${width} halfWidth=${halfWidth} => x:${
child.size.x
} y:${child.size.y} ${child.widthInColumns} (width * (child?.w || 1)) / 2 ${
(width * (child?.widthInColumns || 1)) / 2
}`
);
startingPosX = child.size.x + halfWidth;
@@ -326,21 +256,11 @@ function layoutBlocks(block: Block, db: BlockDB) {
parent.size.y - parent.size.height / 2 + py * (height + padding) + height / 2 + padding;
log.debug(
'abc88 layout blocks (calc) px, py',
'id:',
child.id,
'startingPosX',
startingPosX,
padding,
halfWidth,
'=>',
'x:',
child.size.x,
'y:',
child.size.y,
child.w,
'(width * (child?.w || 1)) / 2',
(width * (child?.w || 1)) / 2
`abc88 layout blocks (calc) px, pyid:${
child.id
}startingPosX${startingPosX}${padding}${halfWidth}=>x:${child.size.x}y:${child.size.y}${
child.widthInColumns
}(width * (child?.w || 1)) / 2${(width * (child?.widthInColumns || 1)) / 2}`
);
}
@@ -348,19 +268,12 @@ function layoutBlocks(block: Block, db: BlockDB) {
if (child.children) {
layoutBlocks(child, db);
}
columnPos += child?.w || 1;
columnPos += child?.widthInColumns || 1;
log.debug('abc88 columnsPos', child, columnPos);
}
}
log.debug(
'layout blocks (<==layoutBlocks)',
block.id,
'x:',
block?.size?.x,
'y:',
block?.size?.y,
'width:',
block?.size?.width
`layout blocks (<==layoutBlocks) ${block.id} x: ${block?.size?.x} y: ${block?.size?.y} width: ${block?.size?.width}`
);
}

View File

@@ -79,12 +79,7 @@ accDescr\s*":"\s* { this.pushState
accDescr\s*"{"\s* { this.pushState("acc_descr_multiline");}
<acc_descr_multiline>[\}] { this.popState(); }
<acc_descr_multiline>[^\}]* return "acc_descr_multiline_value";
"subgraph" return 'subgraph';
"end"\b\s* return 'end';
.*direction\s+TB[^\n]* return 'direction_tb';
.*direction\s+BT[^\n]* return 'direction_bt';
.*direction\s+RL[^\n]* return 'direction_rl';
.*direction\s+LR[^\n]* return 'direction_lr';
// Node end of shape
<NODE>"(((" { this.popState();yy.getLogger().debug('Lex: (('); return "NODE_DEND"; }

View File

@@ -353,7 +353,7 @@ describe('Block diagram', function () {
expect(blocks.length).toBe(2);
const one = blocks[0];
const two = blocks[1];
expect(two.w).toBe(2);
expect(two.widthInColumns).toBe(2);
});
it('empty blocks', async () => {
const str = `block-beta

View File

@@ -130,7 +130,11 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) {
return node;
}
type IOperation = (elem: any, block: any, db: any) => Promise<void>;
async function calculateBlockSize(elem: any, block: any, db: any) {
async function calculateBlockSize(
elem: d3.Selection<SVGGElement, unknown, HTMLElement, any>,
block: any,
db: any
) {
const node = getNodeFromBlock(block, db, false);
if (node.type === 'group') {
return;
@@ -147,9 +151,6 @@ async function calculateBlockSize(elem: any, block: any, db: any) {
export async function insertBlockPositioned(elem: any, block: Block, db: any) {
const node = getNodeFromBlock(block, db, true);
// if (node.type === 'composite') {
// return;
// }
// Add the element to the DOM to size it
const obj = db.getBlock(node.id);
if (obj.type !== 'space') {
@@ -160,7 +161,7 @@ export async function insertBlockPositioned(elem: any, block: Block, db: any) {
}
export async function performOperations(
elem: ContainerElement,
elem: d3.Selection<SVGGElement, unknown, HTMLElement, any>,
blocks: Block[],
db: BlockDB,
operation: IOperation
@@ -173,16 +174,20 @@ export async function performOperations(
}
}
export async function calculateBlockSizes(elem: ContainerElement, blocks: Block[], db: BlockDB) {
export async function calculateBlockSizes(elem: any, blocks: Block[], db: BlockDB) {
await performOperations(elem, blocks, db, calculateBlockSize);
}
export async function insertBlocks(elem: ContainerElement, blocks: Block[], db: BlockDB) {
export async function insertBlocks(
elem: d3.Selection<SVGGElement, unknown, HTMLElement, any>,
blocks: Block[],
db: BlockDB
) {
await performOperations(elem, blocks, db, insertBlockPositioned);
}
export async function insertEdges(
elem: ContainerElement,
elem: any,
edges: Block[],
blocks: Block[],
db: BlockDB,
@@ -214,9 +219,7 @@ export async function insertEdges(
// elem, e, edge, clusterDb, diagramType, graph;
if (edge.start && edge.end) {
const startBlock = db.getBlock(edge.start);
const startBlock2 = g.node(edge.start);
const endBlock = db.getBlock(edge.end);
const endBlock2 = g.node(edge.end);
if (startBlock?.size && endBlock?.size) {
const start = startBlock.size;