adjusted layout and theme support

This commit is contained in:
Knut Sveidqvist
2025-05-08 16:32:40 +02:00
parent 3629e8e480
commit 4f8f929340
3 changed files with 116 additions and 32 deletions

View File

@@ -16,7 +16,7 @@ const defaultTreemapData: TreemapData = {
nodes: [],
levels: new Map(),
};
let outerNodes: TreemapNode[] = [];
let data: TreemapData = structuredClone(defaultTreemapData);
const getConfig = () => {
@@ -32,17 +32,22 @@ const addNode = (node: TreemapNode, level: number) => {
data.nodes.push(node);
data.levels.set(node, level);
if (level === 0) {
outerNodes.push(node);
}
// Set the root node if this is a level 0 node and we don't have a root yet
if (level === 0 && !data.root) {
data.root = node;
}
};
const getRoot = (): TreemapNode | undefined => data.root;
const getRoot = (): TreemapNode | undefined => ({ name: '', children: outerNodes });
const clear = () => {
commonClear();
data = structuredClone(defaultTreemapData);
outerNodes = [];
};
export const db: TreemapDB = {

View File

@@ -1,11 +1,14 @@
import type { Diagram } from '../../Diagram.js';
import type { DiagramRenderer, DrawDefinition } from '../../diagram-api/types.js';
import { selectSvgElement } from '../../rendering-util/selectSvgElement.js';
import { setupViewPortForSVG } from '../../rendering-util/setupViewPortForSVG.js';
import { configureSvgSize } from '../../setupGraphViewbox.js';
import type { TreemapDB, TreemapNode } from './types.js';
import { scaleOrdinal, treemap, hierarchy, format, select } from 'd3';
import { getConfig } from '../../config.js';
const DEFAULT_INNER_PADDING = 5; // Default for inner padding between cells/sections
const DEFAULT_INNER_PADDING = 10; // Default for inner padding between cells/sections
const SECTION_INNER_PADDING = 10; // Default for inner padding between cells/sections
const SECTION_HEADER_HEIGHT = 25;
/**
@@ -17,7 +20,9 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
const treemapInnerPadding = config.padding !== undefined ? config.padding : DEFAULT_INNER_PADDING;
const title = treemapDb.getDiagramTitle();
const root = treemapDb.getRoot();
// const theme = config.getThemeVariables();
const { themeVariables } = getConfig();
console.log('root', root);
if (!root) {
return;
}
@@ -27,8 +32,8 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
const svg = selectSvgElement(id);
// Use config dimensions or defaults
const width = config.nodeWidth ? config.nodeWidth * 10 : 960;
const height = config.nodeHeight ? config.nodeHeight * 10 : 500;
const width = config.nodeWidth ? config.nodeWidth * SECTION_INNER_PADDING : 960;
const height = config.nodeHeight ? config.nodeHeight * SECTION_INNER_PADDING : 500;
const svgWidth = width;
const svgHeight = height + titleHeight;
@@ -42,16 +47,49 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
// Create color scale
const colorScale = scaleOrdinal<string>().range([
'#8dd3c7',
'#ffffb3',
'#bebada',
'#fb8072',
'#80b1d3',
'#fdb462',
'#b3de69',
'#fccde5',
'#d9d9d9',
'#bc80bd',
'transparent',
themeVariables.cScale0,
themeVariables.cScale1,
themeVariables.cScale2,
themeVariables.cScale3,
themeVariables.cScale4,
themeVariables.cScale5,
themeVariables.cScale6,
themeVariables.cScale7,
themeVariables.cScale8,
themeVariables.cScale9,
themeVariables.cScale10,
themeVariables.cScale11,
]);
const colorScalePeer = scaleOrdinal<string>().range([
'transparent',
themeVariables.cScalePeer0,
themeVariables.cScalePeer1,
themeVariables.cScalePeer2,
themeVariables.cScalePeer3,
themeVariables.cScalePeer4,
themeVariables.cScalePeer5,
themeVariables.cScalePeer6,
themeVariables.cScalePeer7,
themeVariables.cScalePeer8,
themeVariables.cScalePeer9,
themeVariables.cScalePeer10,
themeVariables.cScalePeer11,
]);
const colorScaleLabel = scaleOrdinal<string>().range([
'transparent',
themeVariables.cScaleLabel0,
themeVariables.cScaleLabel1,
themeVariables.cScaleLabel2,
themeVariables.cScaleLabel3,
themeVariables.cScaleLabel4,
themeVariables.cScaleLabel5,
themeVariables.cScaleLabel6,
themeVariables.cScaleLabel7,
themeVariables.cScaleLabel8,
themeVariables.cScaleLabel9,
themeVariables.cScaleLabel10,
themeVariables.cScaleLabel11,
]);
// Draw the title if it exists
@@ -80,8 +118,13 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
// Create treemap layout
const treemapLayout = treemap<TreemapNode>()
.size([width, height])
.paddingTop((d) => (d.children && d.children.length > 0 ? SECTION_HEADER_HEIGHT : 0))
.paddingTop((d) =>
d.children && d.children.length > 0 ? SECTION_HEADER_HEIGHT + SECTION_INNER_PADDING : 0
)
.paddingInner(treemapInnerPadding)
.paddingLeft((d) => (d.children && d.children.length > 0 ? SECTION_INNER_PADDING : 0))
.paddingRight((d) => (d.children && d.children.length > 0 ? SECTION_INNER_PADDING : 0))
.paddingBottom((d) => (d.children && d.children.length > 0 ? SECTION_INNER_PADDING : 0))
.round(true);
// Apply the treemap layout to the hierarchy
@@ -103,11 +146,22 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
.attr('width', (d) => d.x1 - d.x0)
.attr('height', SECTION_HEADER_HEIGHT)
.attr('class', 'treemapSectionHeader')
// .attr('fill', (d) => colorScale(d.data.name))
.attr('fill', 'none')
.attr('fill-opacity', 0.6)
// .attr('stroke', (d) => colorScale(d.data.name))
.attr('stroke-width', 0.6);
sections
.append('rect')
.attr('width', (d) => d.x1 - d.x0)
.attr('height', (d) => d.y1 - d.y0)
.attr('class', 'treemapSection')
.attr('fill', (d) => colorScale(d.data.name))
.attr('fill-opacity', 0.6)
.attr('stroke', (d) => colorScale(d.data.name))
.attr('stroke-width', 1);
.attr('stroke', (d) => colorScalePeer(d.data.name))
.attr('stroke-width', 2.0)
.attr('stroke-opacity', 0.4);
// Add section labels
sections
.append('text')
@@ -118,7 +172,7 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
.text((d) => d.data.name)
.attr('font-weight', 'bold')
.style('font-size', '12px')
.style('fill', '#000000')
.style('fill', (d) => colorScaleLabel(d.data.name))
.each(function (d) {
const self = select(this);
const originalText = d.data.name;
@@ -173,7 +227,7 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
.text((d) => (d.value ? valueFormat(d.value) : ''))
.attr('font-style', 'italic')
.style('font-size', '10px')
.style('fill', '#000000');
.style('fill', (d) => colorScaleLabel(d.data.name));
}
// Draw the leaf nodes
@@ -193,13 +247,18 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
.attr('height', (d) => d.y1 - d.y0)
.attr('class', 'treemapLeaf')
.attr('fill', (d) => {
let current = d;
while (current.depth > 1 && current.parent) {
current = current.parent;
}
return colorScale(current.data.name);
// Leaves inherit color from their immediate parent section's name.
// If a leaf is the root itself (no parent), it uses its own name.
return d.parent ? colorScale(d.parent.data.name) : colorScale(d.data.name);
})
.attr('fill-opacity', 0.8);
.attr('fill-opacity', 0.2)
.attr('stroke', (d) => {
// Leaves inherit color from their immediate parent section's name.
// If a leaf is the root itself (no parent), it uses its own name.
return d.parent ? colorScale(d.parent.data.name) : colorScale(d.data.name);
})
.attr('stroke-width', 2.0)
.attr('stroke-opacity', 0.3);
// Add clip paths to prevent text from extending outside nodes
cell
@@ -215,7 +274,9 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
.attr('class', 'treemapLabel')
.attr('x', 4)
.attr('y', 14)
.style('font-size', '11px')
.style('font-size', '34px')
.style('fill', (d) => colorScaleLabel(d.data.name))
// .style('stroke', (d) => colorScaleLabel(d.data.name))
.attr('clip-path', (d, i) => `url(#clip-${id}-${i})`)
.text((d) => d.data.name);
@@ -246,6 +307,25 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
}
});
}
setupViewPortForSVG(svg, 0, 'flowchart', config?.useMaxWidth || false);
const viewBox = svg.attr('viewBox');
const viewBoxParts = viewBox.split(' ');
const viewBoxWidth = viewBoxParts[2];
const viewBoxHeight = viewBoxParts[3];
const viewBoxX = viewBoxParts[0];
const viewBoxY = viewBoxParts[1];
const viewBoxWidthNumber = Number(viewBoxWidth);
const viewBoxHeightNumber = Number(viewBoxHeight);
const viewBoxXNumber = Number(viewBoxX);
const viewBoxYNumber = Number(viewBoxY);
// Adjust the viewBox to account for the title height
svg.attr(
'viewBox',
`${viewBoxXNumber} ${viewBoxYNumber + SECTION_HEADER_HEIGHT} ${viewBoxWidthNumber} ${viewBoxHeightNumber - SECTION_HEADER_HEIGHT}`
);
};
export const renderer: DiagramRenderer = { draw };

View File

@@ -22,9 +22,8 @@ export const getStyles: DiagramStylesProvider = ({
return `
.treemapNode {
fill: pink;
stroke: black;
stroke-width: 1;
// stroke: black;
// stroke-width: 1;
}
.packetByte {
font-size: ${options.byteFontSize};