This commit is contained in:
锦恢 2024-12-31 21:13:04 +08:00
parent 64fdc7408b
commit 1b95ad73c4
4 changed files with 32 additions and 12 deletions

View File

@ -185,6 +185,8 @@ import { Module } from "./render/layout";
* @property {string[]} targets 边的目标节点列表 * @property {string[]} targets 边的目标节点列表
* @property {string} target 边的目标节点 * @property {string} target 边的目标节点
* @property {string} targetPort 边的目标节点的port * @property {string} targetPort 边的目标节点的port
* @property {string} [orginalSource]
* @property {string} [orginalTarget]
* @property {string} [container] 所在容器的 id 可选由布局算法生成 * @property {string} [container] 所在容器的 id 可选由布局算法生成
* @property {ElkSection[]} [sections] 具体的连线规则可选由布局算法生成 * @property {ElkSection[]} [sections] 具体的连线规则可选由布局算法生成
* @property {ElkLayoutOptions} [layoutOptions] 边的布局选项可选 * @property {ElkLayoutOptions} [layoutOptions] 边的布局选项可选

View File

@ -232,7 +232,7 @@ export class NetlistRender {
/** /**
* @description 绘制实体 * @description 绘制实体
* @param {d3.Selection} parentSelection * @param {d3.Selection} parentSelection
* @param {ElkNode} computedLayout * @param {import('../jsdoc').ElkNode} computedLayout
*/ */
async renderEntity(parentSelection, computedLayout) { async renderEntity(parentSelection, computedLayout) {
// node 可能是如下的几类 // node 可能是如下的几类
@ -560,12 +560,14 @@ export class NetlistRender {
for (const edge of connectionEdges) { for (const edge of connectionEdges) {
if (innerPortId2outterPortId.has(edge.source)) { if (innerPortId2outterPortId.has(edge.source)) {
const outterId = innerPortId2outterPortId.get(edge.source); const outterId = innerPortId2outterPortId.get(edge.source);
edge.orginalSource = edge.source;
edge.source = elkNode.id; edge.source = elkNode.id;
edge.sourcePort = outterId; edge.sourcePort = outterId;
} }
if (innerPortId2outterPortId.has(edge.target)) { if (innerPortId2outterPortId.has(edge.target)) {
const outterId = innerPortId2outterPortId.get(edge.target); const outterId = innerPortId2outterPortId.get(edge.target);
edge.orginalTarget = edge.target;
edge.target = elkNode.id; edge.target = elkNode.id;
edge.targetPort = outterId; edge.targetPort = outterId;
} }
@ -576,6 +578,8 @@ export class NetlistRender {
elkNode.edges = []; elkNode.edges = [];
elkNode.layoutOptions = this.defaultLayoutOptions; elkNode.layoutOptions = this.defaultLayoutOptions;
// elkNode.children.push(...portNodes);
elkNode.children.push(...cellNodes); elkNode.children.push(...cellNodes);
elkNode.children.push(...constantNodes); elkNode.children.push(...constantNodes);
elkNode.edges.push(...connectionEdges); elkNode.edges.push(...connectionEdges);
@ -617,7 +621,6 @@ export class NetlistRender {
const layout = s.layout; const layout = s.layout;
await this.renderLine(parentSelection, layout); await this.renderLine(parentSelection, layout);
const { instances } = await this.renderEntity(parentSelection, layout); const { instances } = await this.renderEntity(parentSelection, layout);
const id2selection = new Map(); const id2selection = new Map();

View File

@ -28,27 +28,33 @@ export class InstantiationRender {
/** /**
* @description elknode 关于 例化模块 的数据添加为 d3 数据项目 * @description elknode 关于 例化模块 的数据添加为 d3 数据项目
* @param {ElkNode} node * @param {import('../jsdoc').ElkNode} node
*/ */
addAsD3DataItem(node) { addAsD3DataItem(node) {
const nodeModule = this.rootRender.nameToModule.get(node.renderName); const nodeModule = this.rootRender.nameToModule.get(node.renderName);
const view = nodeModule.view; const view = nodeModule.view;
const textPadding = 5; const textPadding = 5;
const portnames = []; const portnames = [];
// 当前的例化是否为一个展开的例化
this.isExpanded = (node.children || []).length > 0;
const topPadding = this.isExpanded ? 25 : 0;
for (const port of node.ports || []) { for (const port of node.ports || []) {
const isInput = port.x < LAYOUT_CONSTANT.INSTANTIATION_WIDTH; const isInput = port.x < LAYOUT_CONSTANT.INSTANTIATION_WIDTH;
const align = isInput ? 'left': 'end'; const align = isInput ? 'left': 'end';
const portX = isInput ? port.x + textPadding : port.x - textPadding - LAYOUT_CONSTANT.INSTANCE_LEFT_MARGIN - LAYOUT_CONSTANT.INSTANCE_RIGHT_MARGIN; const portX = isInput ? port.x + textPadding : port.x - textPadding - LAYOUT_CONSTANT.INSTANCE_LEFT_MARGIN - LAYOUT_CONSTANT.INSTANCE_RIGHT_MARGIN;
const portY = this.isExpanded ? port.y - 10: port.y;
portnames.push({ portnames.push({
name: port.renderName, name: port.renderName,
x: portX, x: portX,
y: port.y, y: portY,
align align
}); });
} }
this.data.push({ this.data.push({
id: node.id, id: node.id,
type: node.renderName, // 例化模块的模块名字 type: node.renderName, // 例化模块的模块名字
@ -56,7 +62,8 @@ export class InstantiationRender {
y: node.y, y: node.y,
name: node.name, name: node.name,
width: node.width, width: node.width,
height: node.height, height: node.height + topPadding,
topPadding,
text: node.renderName, text: node.renderName,
portnames, portnames,
rx: 3, rx: 3,
@ -83,7 +90,7 @@ export class InstantiationRender {
// 例化模块的方块 // 例化模块的方块
let instances = instantiationSelections.append('rect') let instances = instantiationSelections.append('rect')
.attr('x', LAYOUT_CONSTANT.INSTANCE_LEFT_MARGIN) .attr('x', LAYOUT_CONSTANT.INSTANCE_LEFT_MARGIN)
.attr('y', LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT) .attr('y', d => LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT - d.topPadding)
.attr('width', data => data.width - LAYOUT_CONSTANT.INSTANCE_LEFT_MARGIN - LAYOUT_CONSTANT.INSTANCE_RIGHT_MARGIN) .attr('width', data => data.width - LAYOUT_CONSTANT.INSTANCE_LEFT_MARGIN - LAYOUT_CONSTANT.INSTANCE_RIGHT_MARGIN)
.attr('height', data => data.height - LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT); .attr('height', data => data.height - LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT);
@ -91,7 +98,7 @@ export class InstantiationRender {
// 说明文字 // 说明文字
let texts = instantiationSelections.append('text') let texts = instantiationSelections.append('text')
.attr('x', LAYOUT_CONSTANT.INSTANCE_LEFT_MARGIN) .attr('x', LAYOUT_CONSTANT.INSTANCE_LEFT_MARGIN)
.attr('y', LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT - 8) .attr('y', d => LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT - 8 - d.topPadding)
.attr('dominant-baseline', 'middle') .attr('dominant-baseline', 'middle')
.attr('text-anchor', 'left') .attr('text-anchor', 'left')
.attr('fill', 'var(--foreground)') .attr('fill', 'var(--foreground)')
@ -127,7 +134,7 @@ export class InstantiationRender {
// 增加一个背景方块,防止 svg 点不到 // 增加一个背景方块,防止 svg 点不到
let bgFullScreenSelections = instantiationSelections.append('rect') let bgFullScreenSelections = instantiationSelections.append('rect')
.attr('x', 5 + LAYOUT_CONSTANT.INSTANCE_LEFT_MARGIN) .attr('x', 5 + LAYOUT_CONSTANT.INSTANCE_LEFT_MARGIN)
.attr('y', LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT + 5) .attr('y', d => LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT + 5 - d.topPadding)
.attr('width', 20) .attr('width', 20)
.attr('height', 20) .attr('height', 20)
.attr('opacity', 0) .attr('opacity', 0)
@ -151,7 +158,7 @@ export class InstantiationRender {
// 获取全屏图标 // 获取全屏图标
const element = svgResource.get('full-screen'); const element = svgResource.get('full-screen');
element.setAttribute('x', 5 + LAYOUT_CONSTANT.INSTANCE_LEFT_MARGIN); element.setAttribute('x', 5 + LAYOUT_CONSTANT.INSTANCE_LEFT_MARGIN);
element.setAttribute('y', LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT + 5); element.setAttribute('y', LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT + 5 - data.topPadding);
element.setAttribute('width', 20); element.setAttribute('width', 20);
element.setAttribute('height', 20); element.setAttribute('height', 20);
element.setAttribute('class', 'pointer'); element.setAttribute('class', 'pointer');

View File

@ -52,7 +52,15 @@ export class WireRender {
const targetMargin = getMarginParamter(targetPort); const targetMargin = getMarginParamter(targetPort);
beginPoint.x -= sourceMargin.rightMargin; beginPoint.x -= sourceMargin.rightMargin;
// 特殊情况: targetPort 为 undefined
if (targetPort === undefined) {
const port = id2port.get(edge.orginalTarget);
// TODO: 检查正确性
endPoint.x -= LAYOUT_CONSTANT.INSTANCE_RIGHT_MARGIN;
} else {
endPoint.x += targetMargin.leftMargin; endPoint.x += targetMargin.leftMargin;
}
for (let i = 0; i < points.length; ++ i) { for (let i = 0; i < points.length; ++ i) {
// 根据点的信息创建 path // 根据点的信息创建 path