5237 Adding rectWith title shape

This commit is contained in:
Knut Sveidqvist 2024-06-13 16:25:41 +02:00
parent 94512c0780
commit e2e652ae0f
4 changed files with 160 additions and 1 deletions

View File

@ -231,6 +231,15 @@ const extract = (_doc) => {
const look = config.look;
resetDataFetching();
dataFetcher(undefined, getRootDocV2(), diagramStates, nodes, edges, true, look);
nodes.forEach((node) => {
if (Array.isArray(node.label)) {
// add the rest as description
node.description = node.label.slice(1);
// add first description as label
node.label = node.label[0];
}
});
console.log('nodes after extract', nodes);
};
/**

View File

@ -8,6 +8,7 @@ import { forkJoin } from './shapes/forkJoin.ts';
import { choice } from './shapes/choice.ts';
import { note } from './shapes/note.ts';
import { stadium } from './shapes/stadium.js';
import { rectWithTitle } from './shapes/rectWithTitle.js';
import { getConfig } from '$root/diagram-api/diagramAPI.js';
import { subroutine } from './shapes/subroutine.js';
import { cylinder } from './shapes/cylinder.js';
@ -36,7 +37,7 @@ const shapes = {
choice,
note,
roundedRect,
rectWithTitle: roundedRect,
rectWithTitle,
squareRect,
stadium,
subroutine,
@ -58,6 +59,8 @@ export const insertNode = async (elem, node, dir) => {
let newEl;
let el;
console.log('node DDD', node);
//special check for rect shape (with or without rounded corners)
if (node.shape === 'rect') {
if (node.rx && node.ry) {

View File

@ -0,0 +1,146 @@
import type { Node, RectOptions } from '$root/rendering-util/types.d.ts';
import { select } from 'd3';
import { evaluate } from '$root/diagrams/common/common.js';
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
import createLabel from '../createLabel.js';
import intersect from '../intersect/index.js';
import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shapes/handdrawnStyles.js';
import rough from 'roughjs';
import { getConfig } from '$root/diagram-api/diagramAPI.js';
import { createRoundedRectPathD } from './roundedRectPath.js';
import { log } from '$root/logger.js';
export const rectWithTitle = async (parent: SVGElement, node: Node) => {
let classes;
if (!node.cssClasses) {
classes = 'node default';
} else {
classes = 'node ' + node.cssClasses;
}
// Add outer g element
const shapeSvg = parent
// @ts-ignore - d3 typings are not correct
.insert('g')
.attr('class', classes)
.attr('id', node.domId || node.id);
// Create the title label and insert it after the rect
const g = shapeSvg.insert('g');
const label = shapeSvg.insert('g').attr('class', 'label');
const description = node.description;
let title = node.label;
const text = label.node().appendChild(createLabel(title, node.labelStyle, true, true));
let bbox = { width: 0, height: 0 };
if (evaluate(getConfig()?.flowchart?.htmlLabels)) {
const div = text.children[0];
const dv = select(text);
bbox = div.getBoundingClientRect();
dv.attr('width', bbox.width);
dv.attr('height', bbox.height);
}
log.info('Text 2', description);
const textRows = description || [];
let titleBox = text.getBBox();
const descr = label
.node()
.appendChild(
createLabel(textRows.join ? textRows.join('<br/>') : textRows, node.labelStyle, true, true)
);
if (evaluate(getConfig()?.flowchart?.htmlLabels)) {
const div = descr.children[0];
const dv = select(descr);
bbox = div.getBoundingClientRect();
dv.attr('width', bbox.width);
dv.attr('height', bbox.height);
}
const halfPadding = (node.padding || 0) / 2;
select(descr).attr(
'transform',
'translate( ' +
(bbox.width > titleBox.width ? 0 : (titleBox.width - bbox.width) / 2) +
', ' +
(titleBox.height + halfPadding + 5) +
')'
);
select(text).attr(
'transform',
'translate( ' +
(bbox.width < titleBox.width ? 0 : -(titleBox.width - bbox.width) / 2) +
', ' +
0 +
')'
);
// Get the size of the label
// Bounding box for title and text
bbox = label.node().getBBox();
// Center the label
label.attr(
'transform',
'translate(' + -bbox.width / 2 + ', ' + (-bbox.height / 2 - halfPadding + 3) + ')'
);
const totalWidth = bbox.width + (node.padding || 0);
const totalHeight = bbox.height + (node.padding || 0);
const x = -bbox.width / 2 - halfPadding;
const y = -bbox.height / 2 - halfPadding;
let rect;
let innerLine;
if (node.look === 'handdrawn') {
// @ts-ignore No typings for rough
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const roughNode = rc.path(
createRoundedRectPathD(x, y, totalWidth, totalHeight, node.rx || 0),
options
);
const roughLine = rc.line(
-bbox.width / 2 - halfPadding,
-bbox.height / 2 - halfPadding + titleBox.height + halfPadding,
bbox.width / 2 + halfPadding,
-bbox.height / 2 - halfPadding + titleBox.height + halfPadding,
options
);
innerLine = shapeSvg.insert(() => {
log.debug('Rough node insert CXC', roughNode);
return roughLine;
}, ':first-child');
rect = shapeSvg.insert(() => {
log.debug('Rough node insert CXC', roughNode);
return roughNode;
}, ':first-child');
} else {
rect = g.insert('rect', ':first-child');
innerLine = g.insert('line');
rect
.attr('class', 'outer title-state')
.attr('x', -bbox.width / 2 - halfPadding)
.attr('y', -bbox.height / 2 - halfPadding)
.attr('width', bbox.width + (node.padding || 0))
.attr('height', bbox.height + (node.padding || 0));
innerLine
.attr('class', 'divider')
.attr('x1', -bbox.width / 2 - halfPadding)
.attr('x2', bbox.width / 2 + halfPadding)
.attr('y1', -bbox.height / 2 - halfPadding + titleBox.height + halfPadding)
.attr('y2', -bbox.height / 2 - halfPadding + titleBox.height + halfPadding);
}
updateNodeBounds(node, rect);
node.intersect = function (point) {
return intersect.rect(node, point);
};
return shapeSvg;
};

View File

@ -13,6 +13,7 @@ export type CheckFitFunction = (text: MarkdownLine) => boolean;
interface Node {
id: string;
label?: string;
description?: string[];
parentId?: string;
position?: string; // Keep, this is for notes 'left of', 'right of', etc. Move into nodeNode
cssStyles?: string; // Renamed from `styles` to `cssStyles`