实现动态增加线宽
This commit is contained in:
parent
7a6ed915d0
commit
0b8e986990
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
window.readNetFile = async () => {
|
window.readNetFile = async () => {
|
||||||
const inputVcdFile = 'full_adder.json';
|
const inputVcdFile = 'IF_ID.json';
|
||||||
const skin = 'dide.skin';
|
const skin = 'dide.skin';
|
||||||
const r1 = await fetch(inputVcdFile);
|
const r1 = await fetch(inputVcdFile);
|
||||||
const r2 = await fetch(skin);
|
const r2 = await fetch(skin);
|
||||||
@ -23,7 +23,7 @@
|
|||||||
const skinBinary = await r2.arrayBuffer();
|
const skinBinary = await r2.arrayBuffer();
|
||||||
return [ netJson, skinBinary ];
|
return [ netJson, skinBinary ];
|
||||||
}
|
}
|
||||||
window.moduleName = 'full_adder';
|
window.moduleName = 'IF_ID';
|
||||||
// window.avoidWasm = 'avoid.wasm';
|
// window.avoidWasm = 'avoid.wasm';
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
@ -75,6 +75,7 @@
|
|||||||
{{ t('bold-multi-width-wire') }}
|
{{ t('bold-multi-width-wire') }}
|
||||||
</span>
|
</span>
|
||||||
<el-switch
|
<el-switch
|
||||||
|
@change="onBoldMultiWidthWireChange"
|
||||||
v-model="globalSetting.boldMultiWidthWire"
|
v-model="globalSetting.boldMultiWidthWire"
|
||||||
active-text="ON"
|
active-text="ON"
|
||||||
inactive-text="OFF"
|
inactive-text="OFF"
|
||||||
@ -166,12 +167,13 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { globalSetting } from '@/hook/global';
|
import { globalLookup, globalSetting } from '@/hook/global';
|
||||||
import { reactive, defineComponent, watch, ref, onMounted } from 'vue';
|
import { reactive, defineComponent, watch, ref, onMounted } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { languageSetting } from './language';
|
import { languageSetting } from './language';
|
||||||
import { crossDotStyle, onConnectStyleChange } from './cross-dot-style';
|
import { crossDotStyle, onConnectStyleChange } from './cross-dot-style';
|
||||||
import { colorManager, onCellColorChange, onGeneralColorChange, predefinedColors } from './color';
|
import { colorManager, onCellColorChange, onGeneralColorChange, predefinedColors } from './color';
|
||||||
|
import { LINE_WIDTH } from '@/hook/render/layout';
|
||||||
|
|
||||||
defineComponent({ name: "dide-setting" });
|
defineComponent({ name: "dide-setting" });
|
||||||
const { t, locale } = useI18n();
|
const { t, locale } = useI18n();
|
||||||
@ -199,7 +201,6 @@ function onlanguagechange(code) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function onRenderArrowChange() {
|
function onRenderArrowChange() {
|
||||||
const rootStyles = getComputedStyle(document.documentElement);
|
|
||||||
if (globalSetting.renderArrow) {
|
if (globalSetting.renderArrow) {
|
||||||
document.documentElement.style.setProperty(`--line-arrow-opacity`, '1');
|
document.documentElement.style.setProperty(`--line-arrow-opacity`, '1');
|
||||||
} else {
|
} else {
|
||||||
@ -207,6 +208,26 @@ function onRenderArrowChange() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onBoldMultiWidthWireChange() {
|
||||||
|
const netlist = globalLookup.netlistRender;
|
||||||
|
const renderView = netlist.renderView;
|
||||||
|
const stack = [renderView];
|
||||||
|
while (stack.length > 0) {
|
||||||
|
const view = stack.pop();
|
||||||
|
view.wireRender.lineSelections
|
||||||
|
.attr('stroke-width', d => {
|
||||||
|
console.log('enter');
|
||||||
|
|
||||||
|
const incrementWidth = globalSetting.boldMultiWidthWire ? 2 : 0;
|
||||||
|
return d.width > 1 ? LINE_WIDTH + incrementWidth: LINE_WIDTH;
|
||||||
|
});
|
||||||
|
for (const id of view.id2children.keys()) {
|
||||||
|
const subView = view.getChild(id);
|
||||||
|
stack.push(subView);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
colorManager.initColor();
|
colorManager.initColor();
|
||||||
});
|
});
|
||||||
|
@ -15,6 +15,7 @@ import { dotConnect } from './yosys';
|
|||||||
import { CrossDotRender } from './cross-dot';
|
import { CrossDotRender } from './cross-dot';
|
||||||
import { RangeTreeMap } from '../algorithm/range-tree';
|
import { RangeTreeMap } from '../algorithm/range-tree';
|
||||||
import { ConstantRender } from './constant';
|
import { ConstantRender } from './constant';
|
||||||
|
import { RenderViewNode } from './render-view';
|
||||||
|
|
||||||
export class NetlistRender {
|
export class NetlistRender {
|
||||||
/**
|
/**
|
||||||
@ -209,15 +210,16 @@ export class NetlistRender {
|
|||||||
// 底层模块
|
// 底层模块
|
||||||
const topModule = this.nameToModule.get(this.topModuleName);
|
const topModule = this.nameToModule.get(this.topModuleName);
|
||||||
|
|
||||||
// 生成连接
|
|
||||||
await this.renderLine(g, computedLayout, topModule);
|
|
||||||
|
|
||||||
// 生成实体
|
|
||||||
await this.renderEntity(g, computedLayout, topModule);
|
|
||||||
|
|
||||||
// svg 挂载为全局注册的 selection
|
// svg 挂载为全局注册的 selection
|
||||||
this.selection = svg;
|
this.selection = svg;
|
||||||
this.g = g;
|
|
||||||
|
this.renderView = new RenderViewNode(g);
|
||||||
|
|
||||||
|
// 生成连接
|
||||||
|
await this.renderLine(this.renderView, computedLayout, topModule);
|
||||||
|
|
||||||
|
// 生成实体
|
||||||
|
await this.renderEntity(this.renderView, computedLayout, topModule);
|
||||||
|
|
||||||
// 注册平移和缩放
|
// 注册平移和缩放
|
||||||
this.registerRenderTransform(g);
|
this.registerRenderTransform(g);
|
||||||
@ -235,10 +237,10 @@ export class NetlistRender {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 绘制实体
|
* @description 绘制实体
|
||||||
* @param {d3.Selection} parentSelection
|
* @param {RenderViewNode} view
|
||||||
* @param {import('../jsdoc').ElkNode} computedLayout
|
* @param {import('../jsdoc').ElkNode} computedLayout
|
||||||
*/
|
*/
|
||||||
async renderEntity(parentSelection, computedLayout) {
|
async renderEntity(view, computedLayout) {
|
||||||
// node 可能是如下的几类
|
// node 可能是如下的几类
|
||||||
// - module 的 port
|
// - module 的 port
|
||||||
// - 器件(基础器件 & 例化模块)
|
// - 器件(基础器件 & 例化模块)
|
||||||
@ -246,11 +248,11 @@ export class NetlistRender {
|
|||||||
const skinManager = globalLookup.skinManager;
|
const skinManager = globalLookup.skinManager;
|
||||||
|
|
||||||
// 创建各个主要实体的 render
|
// 创建各个主要实体的 render
|
||||||
this.cellRender = new CellRender(parentSelection, this);
|
view.cellRender = new CellRender(view.g, this);
|
||||||
this.portRender = new PortRender(parentSelection, this);
|
view.portRender = new PortRender(view.g, this);
|
||||||
this.instantiationRender = new InstantiationRender(parentSelection, this);
|
view.instantiationRender = new InstantiationRender(view.g, this);
|
||||||
this.connectionRender = new ConnectionRender(parentSelection, this);
|
view.connectionRender = new ConnectionRender(view.g, this);
|
||||||
this.constantRender = new ConstantRender(parentSelection, this);
|
view.constantRender = new ConstantRender(view.g, this);
|
||||||
|
|
||||||
for (const node of computedLayout.children) {
|
for (const node of computedLayout.children) {
|
||||||
// 只计算形体的,因为 连接点 非常小,几乎不影响布局
|
// 只计算形体的,因为 连接点 非常小,几乎不影响布局
|
||||||
@ -260,42 +262,40 @@ export class NetlistRender {
|
|||||||
if (skin) {
|
if (skin) {
|
||||||
// 具有 skin 的器件
|
// 具有 skin 的器件
|
||||||
const element = skin.meta.svgDoc.documentElement.cloneNode(true);
|
const element = skin.meta.svgDoc.documentElement.cloneNode(true);
|
||||||
this.cellRender.addAsD3DataItem(node, element);
|
view.cellRender.addAsD3DataItem(node, element);
|
||||||
} else {
|
} else {
|
||||||
if (node.renderType === 'port') {
|
if (node.renderType === 'port') {
|
||||||
this.portRender.addAsD3DataItem(node);
|
view.portRender.addAsD3DataItem(node);
|
||||||
} else if (node.renderType === 'instance') {
|
} else if (node.renderType === 'instance') {
|
||||||
// 没有 skin 的器件或者端口
|
// 没有 skin 的器件或者端口
|
||||||
this.instantiationRender.addAsD3DataItem(node);
|
view.instantiationRender.addAsD3DataItem(node);
|
||||||
} else if (node.renderType === 'constant') {
|
} else if (node.renderType === 'constant') {
|
||||||
this.constantRender.addAsD3DataItem(node);
|
view.constantRender.addAsD3DataItem(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果存在 port,绘制 port
|
// 如果存在 port,绘制 port
|
||||||
for (const cellPort of node.ports || []) {
|
for (const cellPort of node.ports || []) {
|
||||||
this.connectionRender.addAsD3DataItem(cellPort, node);
|
view.connectionRender.addAsD3DataItem(cellPort, node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ports = this.portRender.render();
|
view.portRender.render();
|
||||||
const instances = this.instantiationRender.render();
|
view.instantiationRender.render();
|
||||||
const cells = this.cellRender.render();
|
view.cellRender.render();
|
||||||
const connections = this.connectionRender.render();
|
view.connectionRender.render();
|
||||||
const constants = this.constantRender.render();
|
view.constantRender.render();
|
||||||
|
|
||||||
return { ports, instances, cells, connections };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 绘制连线和交叉点
|
* @description 绘制连线和交叉点
|
||||||
* @param {d3.Selection} parentSelection
|
* @param {RenderViewNode} view
|
||||||
* @param {ElkNode} computedLayout
|
* @param {ElkNode} computedLayout
|
||||||
* @param {Module} module
|
* @param {Module} module
|
||||||
*/
|
*/
|
||||||
async renderLine(parentSelection, computedLayout, module) {
|
async renderLine(view, computedLayout, module) {
|
||||||
this.wireRender = new WireRender(parentSelection, this);
|
view.wireRender = new WireRender(view.g, this);
|
||||||
this.crossDotRender = new CrossDotRender(parentSelection, this);
|
view.crossDotRender = new CrossDotRender(view.g, this);
|
||||||
|
|
||||||
// 建立关于 port 的索引
|
// 建立关于 port 的索引
|
||||||
const id2port = new Map();
|
const id2port = new Map();
|
||||||
@ -316,7 +316,7 @@ export class NetlistRender {
|
|||||||
points.push(point);
|
points.push(point);
|
||||||
}
|
}
|
||||||
points.push(section.endPoint);
|
points.push(section.endPoint);
|
||||||
this.wireRender.addAsD3DataItems(points, edge, id2port, width);
|
view.wireRender.addAsD3DataItems(points, edge, id2port, width);
|
||||||
|
|
||||||
// 加入 range tree 中
|
// 加入 range tree 中
|
||||||
for (let i = 0; i < points.length - 1; ++ i) {
|
for (let i = 0; i < points.length - 1; ++ i) {
|
||||||
@ -337,14 +337,14 @@ export class NetlistRender {
|
|||||||
for (const point of section.bendPoints || []) {
|
for (const point of section.bendPoints || []) {
|
||||||
const degree = rangeTree.getDegree(point);
|
const degree = rangeTree.getDegree(point);
|
||||||
if (degree >= 3) {
|
if (degree >= 3) {
|
||||||
this.crossDotRender.addAsD3DataItem(point.x, point.y);
|
view.crossDotRender.addAsD3DataItem(point.x, point.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.wireRender.render();
|
view.wireRender.render();
|
||||||
this.crossDotRender.render();
|
view.crossDotRender.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -614,34 +614,31 @@ export class NetlistRender {
|
|||||||
this.zoom.translateBy(this.selection, deltaX, deltaY);
|
this.zoom.translateBy(this.selection, deltaX, deltaY);
|
||||||
|
|
||||||
const svg = this.selection;
|
const svg = this.selection;
|
||||||
const g = this.g;
|
const g = this.renderView.g;
|
||||||
|
|
||||||
g.selectAll('*').remove();
|
g.selectAll('*').remove();
|
||||||
|
this.renderView.id2children.clear();
|
||||||
|
|
||||||
// 开始递归地进行渲染
|
// 开始递归地进行渲染
|
||||||
const renderStack = [
|
const renderStack = [
|
||||||
{
|
{
|
||||||
parentSelection: g,
|
view: this.renderView,
|
||||||
layout: computedLayout
|
layout: computedLayout
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
while (renderStack.length > 0) {
|
while (renderStack.length > 0) {
|
||||||
const s = renderStack.pop();
|
const s = renderStack.pop();
|
||||||
const parentSelection = s.parentSelection;
|
const view = s.view;
|
||||||
const layout = s.layout;
|
const layout = s.layout;
|
||||||
|
|
||||||
const layoutName = layout.renderName || this.topModuleName;
|
const layoutName = layout.renderName || this.topModuleName;
|
||||||
const module = this.nameToModule.get(layoutName);
|
const module = this.nameToModule.get(layoutName);
|
||||||
|
|
||||||
await this.renderLine(parentSelection, layout, module);
|
await this.renderLine(view, layout, module);
|
||||||
const { instances } = await this.renderEntity(parentSelection, layout, module);
|
await this.renderEntity(view, layout, module);
|
||||||
|
|
||||||
const id2selection = new Map();
|
const id2selection = view.instantiationRender.id2selection;
|
||||||
instances.each(function(data) {
|
|
||||||
const selection = d3.select(this);
|
|
||||||
id2selection.set(data.id, selection);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 将需要渲染子图的部分扔进渲染器
|
// 将需要渲染子图的部分扔进渲染器
|
||||||
for (const node of layout.children || []) {
|
for (const node of layout.children || []) {
|
||||||
@ -649,8 +646,10 @@ export class NetlistRender {
|
|||||||
|
|
||||||
if (subChildren.length > 0) {
|
if (subChildren.length > 0) {
|
||||||
const selection = id2selection.get(node.id);
|
const selection = id2selection.get(node.id);
|
||||||
|
const subView = new RenderViewNode(selection);
|
||||||
|
view.setChild(node.id, subView);
|
||||||
renderStack.push({
|
renderStack.push({
|
||||||
parentSelection: selection,
|
view: subView,
|
||||||
layout: node
|
layout: node
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -702,37 +701,41 @@ export class NetlistRender {
|
|||||||
this.zoom.translateBy(this.selection, deltaX, deltaY);
|
this.zoom.translateBy(this.selection, deltaX, deltaY);
|
||||||
|
|
||||||
const svg = this.selection;
|
const svg = this.selection;
|
||||||
const g = this.g;
|
const g = this.renderView.g;
|
||||||
|
|
||||||
g.selectAll('*').remove();
|
g.selectAll('*').remove();
|
||||||
|
this.renderView.id2children.clear();
|
||||||
|
|
||||||
// 开始递归地进行渲染
|
// 开始递归地进行渲染
|
||||||
const renderStack = [
|
const renderStack = [
|
||||||
{
|
{
|
||||||
parentSelection: g,
|
view: this.renderView,
|
||||||
layout: computedLayout
|
layout: computedLayout
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
while (renderStack.length > 0) {
|
while (renderStack.length > 0) {
|
||||||
const s = renderStack.pop();
|
const s = renderStack.pop();
|
||||||
const parentSelection = s.parentSelection;
|
const view = s.view;
|
||||||
const layout = s.layout;
|
const layout = s.layout;
|
||||||
await this.renderLine(parentSelection, layout);
|
|
||||||
const { instances } = await this.renderEntity(parentSelection, layout);
|
const layoutName = layout.renderName || this.topModuleName;
|
||||||
const id2selection = new Map();
|
const module = this.nameToModule.get(layoutName);
|
||||||
instances.each(function(data) {
|
|
||||||
const selection = d3.select(this);
|
await this.renderLine(view, layout, module);
|
||||||
id2selection.set(data.id, selection);
|
await this.renderEntity(view, layout, module);
|
||||||
});
|
|
||||||
|
const id2selection = view.instantiationRender.id2selection;
|
||||||
|
|
||||||
// 将需要渲染子图的部分扔进渲染器
|
// 将需要渲染子图的部分扔进渲染器
|
||||||
for (const node of layout.children || []) {
|
for (const node of layout.children || []) {
|
||||||
const subChildren = node.children || [];
|
const subChildren = node.children || [];
|
||||||
if (subChildren.length > 0) {
|
if (subChildren.length > 0) {
|
||||||
const selection = id2selection.get(node.id);
|
const selection = id2selection.get(node.id);
|
||||||
|
const subView = new RenderViewNode(selection);
|
||||||
|
view.id2children.set(node.id, subView);
|
||||||
renderStack.push({
|
renderStack.push({
|
||||||
parentSelection: selection,
|
view: subView,
|
||||||
layout: node
|
layout: node
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -235,6 +235,15 @@ export class InstantiationRender {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.selections = instantiationSelections;
|
this.selections = instantiationSelections;
|
||||||
|
|
||||||
|
const id2selection = new Map();
|
||||||
|
instantiationSelections.each(function(data) {
|
||||||
|
const selection = d3.select(this);
|
||||||
|
id2selection.set(data.id, selection);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.id2selection = id2selection;
|
||||||
|
|
||||||
return instantiationSelections;
|
return instantiationSelections;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +118,6 @@ export class WireRender {
|
|||||||
.attr("fill", "none")
|
.attr("fill", "none")
|
||||||
.attr('stroke', 'var(--wire-color)')
|
.attr('stroke', 'var(--wire-color)')
|
||||||
|
|
||||||
this.lineSelections = lineSelections;
|
|
||||||
const arrows = new Map();
|
const arrows = new Map();
|
||||||
|
|
||||||
let arrowSelections = this.selection.selectAll('svg.line-arrow')
|
let arrowSelections = this.selection.selectAll('svg.line-arrow')
|
||||||
@ -196,21 +195,23 @@ export class WireRender {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
if (globalSetting.renderAnimation) {
|
// if (globalSetting.renderAnimation) {
|
||||||
lineSelections = lineSelections
|
// lineSelections = lineSelections
|
||||||
.transition()
|
// .transition()
|
||||||
.duration(1000);
|
// .duration(1000);
|
||||||
}
|
// }
|
||||||
|
|
||||||
lineSelections
|
lineSelections
|
||||||
.attr('stroke-width', d => {
|
.attr('stroke-width', d => {
|
||||||
const incrementWidth = globalSetting.boldMultiWidthWire ? 1 : 0;
|
const incrementWidth = globalSetting.boldMultiWidthWire ? 2 : 0;
|
||||||
return d.width > 1 ? LINE_WIDTH + incrementWidth: LINE_WIDTH;
|
return d.width > 1 ? LINE_WIDTH + incrementWidth: LINE_WIDTH;
|
||||||
})
|
})
|
||||||
.each(function (data) {
|
.each(function (data) {
|
||||||
const selection = d3.select(this);
|
const selection = d3.select(this);
|
||||||
// const manager = _this.createDataManager(selection, data);
|
// const manager = _this.createDataManager(selection, data);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.lineSelections = lineSelections;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user