/** * 用于维护所有的 波形容器视图 * 设计参考文档:https://nc-ai-lab.feishu.cn/wiki/Fy3ZwtbYbiatmxkhOp2cyHSFnlw */ import { groupColorDispatcher } from "@/components/sidebar/manage-group"; import { globalLookup } from "./global"; import { getSmartCurrentSignalValue } from "./utils"; /** * @typedef {Object} ViewIterConfig * @property {boolean} returnGroup */ /** * @namespace WaveContainerView */ export const WaveContainerView = { /** * @description 增加 一个信号,并创建它的若干个视图,并计算出它当前时刻的值 * @param {WireItem} signal */ add(signal) { if (globalLookup.currentWires.has(signal)) { return; } // 增加高效 CRUD 视图 globalLookup.currentWires.add(signal); // 上面的 视图 的 string, signal 字典版本 globalLookup.link2CurrentWires.set(signal.link, signal); // 增加 sidebar 渲染视图 // TODO : 支持更加复杂的视图加入 globalLookup.currentWiresRenderView.push({ signalInfo: { name: signal.name, link: signal.link, size: signal.size, }, groupInfo: { name: '', color: '', collapse: false }, renderType: 0, children: [] }); // 增加当前波形值视图 const changoItem = globalLookup.chango[signal.link]; globalLookup.currentSignalValues[signal.link] = getSmartCurrentSignalValue(changoItem, globalLookup.currentTime); }, /** * * @param {WireItem} signal */ delete(signal) { const renderView = globalLookup.currentWiresRenderView; globalLookup.currentWires.delete(signal); globalLookup.link2CurrentWires.delete(signal.link); delete globalLookup.currentSignalValues[signal.link]; // 从 currentWiresRenderView 中删除 // 此处需要考虑到处于 group 中的 link 的情况 const { index, childIndex } = findViewIndexTuple(signal.link); function deleteElement(container, index) { const tailElements = container.slice(index + 1); container.length = index; tailElements.forEach(el => container.push(el)); } if (childIndex >= 0) { // 删除 group 内元素 const view = renderView[index]; deleteElement(view.children, childIndex); // 如果 group 空了,则也删除 if (view.children.length === 0) { deleteElement(renderView, index); groupColorDispatcher.put(view.groupInfo.color); } } else if (index >= 0) { // 删除总体的元素 deleteElement(renderView, index); } }, /** * * @param {WireItem} signal * @returns {boolean} */ has(signal) { return globalLookup.currentWires.has(signal); } }; /** * @description 找到位于嵌套结构中的索引 * @param {string} link * @returns {{ index: number, childIndex: number }} index: 位于 renderView 的索引,位于 group 的 children 中的索引 */ function findViewIndexTuple(link) { const renderView = globalLookup.currentWiresRenderView; for (let i = 0; i < renderView.length; ++ i) { const view = renderView[i]; if (view.signalInfo.link === link) { return { index: i, childIndex: -1 }; } for (let j = 0; j < view.children.length; ++ j) { const child = view.children[j]; if (child.signalInfo.link === link) { return { index: i, childIndex: j }; } } } return { index: -1, childIndex: -1 }; } export function findViewIndexByLink(link) { const renderView = globalLookup.currentWiresRenderView; let i = 0; while (i < renderView.length && renderView[i].signalInfo.link !== link) { ++ i; } if (i < renderView.length) { return i; } else { return -1; } } function makeFullSignalNameDeps(signal) { const deps = []; while (signal) { if (signal.name && signal.type) { deps.push(signal); } signal = signal.parent; } let htmlString = ''; for (let i = deps.length - 1; i >= 0; -- i) { const mod = deps[i]; // const displayName = mod.name.length > 6 ? mod.name.substring(0, 6) + '...' : mod.name; const iconClass = makeIconClass(mod); const iconText = ` ${mod.name}`; htmlString += iconText; if (i > 0) { htmlString += '
'; } } htmlString = '
' + htmlString + '
'; return htmlString; } /** * * @param {ViewIterConfig} iterConfig * @returns {Generator} */ export function* genOrderedLinks(iterConfig) { const iterGroup = (iterConfig || {}).iterGroup || false; for (const view of globalLookup.currentWiresRenderView) { if (view.renderType === 0) { yield view.signalInfo.link; } else { if (iterGroup) { // groupLink 都会以 -group 结尾 yield view.signalInfo.link; } for (const child of view.children) { yield child.signalInfo.link; } } } }