/** * 获取波形预览组件的样式内容(纯 CSS,不包含 style 标签) */ export function getWaveformPreviewContent(): string { return ` /* 波形预览组件样式 */ .waveform-preview { margin: 16px 0; border: 1px solid var(--vscode-panel-border); border-radius: 12px; overflow: hidden; background: var(--vscode-editor-background); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); transition: box-shadow 0.3s ease, transform 0.2s ease; } .waveform-preview:hover { box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15); transform: translateY(-2px); } .waveform-preview-header { display: flex; align-items: center; justify-content: space-between; padding: 14px 16px; background: linear-gradient(135deg, var(--vscode-input-background) 0%, var(--vscode-editor-background) 100%); border-bottom: 1px solid var(--vscode-panel-border); backdrop-filter: blur(10px); } .waveform-preview-title { display: flex; align-items: center; gap: 10px; font-size: 14px; font-weight: 600; color: var(--vscode-foreground); letter-spacing: 0.3px; } .waveform-preview-title svg { width: 18px; height: 18px; color: var(--vscode-button-background); filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.2)); } .waveform-expand-btn { padding: 6px 14px; background: var(--vscode-button-background); color: var(--vscode-button-foreground); border: none; border-radius: 6px; cursor: pointer; font-size: 12px; font-weight: 500; display: flex; align-items: center; gap: 6px; transition: all 0.2s ease; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } .waveform-expand-btn:hover { background: var(--vscode-button-hoverBackground); transform: translateY(-1px); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15); } .waveform-expand-btn:active { transform: translateY(0); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); } .waveform-expand-btn svg { width: 14px; height: 14px; } .waveform-preview-content { padding: 12px; overflow: hidden; position: relative; background: var(--vscode-editor-background); } .waveform-preview-canvas { width: 100%; height: auto; } .waveform-preview-placeholder { display: flex; flex-direction: column; align-items: center; justify-content: center; color: var(--vscode-descriptionForeground); font-size: 13px; text-align: center; padding: 20px; } .waveform-preview-placeholder svg { width: 48px; height: 48px; margin-bottom: 12px; opacity: 0.5; } .waveform-info { margin-top: 8px; font-size: 12px; color: var(--vscode-descriptionForeground); } .waveform-mini-viewer { width: 100%; height: auto; min-height: 120px; background: var(--vscode-editor-background); position: relative; overflow: hidden; } .waveform-loading { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: var(--vscode-descriptionForeground); font-size: 12px; } `; } /** * 获取波形预览组件的 JavaScript 代码 */ export function getWaveformPreviewScript(): string { return ` /** * 创建波形预览组件 */ function createWaveformPreview(vcdFilePath, fileName) { const previewDiv = document.createElement('div'); previewDiv.className = 'waveform-preview'; // 头部 const header = document.createElement('div'); header.className = 'waveform-preview-header'; const title = document.createElement('div'); title.className = 'waveform-preview-title'; title.innerHTML = \` 波形预览 - \${fileName} \`; const expandBtn = document.createElement('button'); expandBtn.className = 'waveform-expand-btn'; expandBtn.innerHTML = \` 展开查看 \`; expandBtn.onclick = () => openFullWaveform(vcdFilePath); header.appendChild(title); header.appendChild(expandBtn); // 内容区域 - 创建一个唯一ID的容器用于显示波形 const content = document.createElement('div'); content.className = 'waveform-preview-content'; const miniViewerId = 'waveform-mini-' + Date.now(); const miniViewer = document.createElement('div'); miniViewer.id = miniViewerId; miniViewer.className = 'waveform-mini-viewer'; // 添加加载提示 const loadingDiv = document.createElement('div'); loadingDiv.className = 'waveform-loading'; loadingDiv.textContent = '正在加载波形预览...'; miniViewer.appendChild(loadingDiv); content.appendChild(miniViewer); previewDiv.appendChild(header); previewDiv.appendChild(content); // 异步加载波形数据 loadMiniWaveform(miniViewerId, vcdFilePath, loadingDiv); return previewDiv; } /** * 加载迷你波形预览 */ async function loadMiniWaveform(containerId, vcdFilePath, loadingDiv) { try { // 请求 VCD 文件信息 vscode.postMessage({ command: 'getVCDInfo', vcdFilePath: vcdFilePath, containerId: containerId }); } catch (error) { console.error('加载波形预览失败:', error); loadingDiv.textContent = '波形预览加载失败'; loadingDiv.style.color = 'var(--vscode-errorForeground)'; } } /** * 渲染波形预览信息 */ function renderWaveformInfo(containerId, vcdInfo) { const container = document.getElementById(containerId); if (!container) return; // 清空容器 container.innerHTML = ''; // 绘制真实波形 const waveformSvg = document.createElement('div'); waveformSvg.innerHTML = drawRealWaveform(vcdInfo.signals || []); container.appendChild(waveformSvg); } /** * 绘制真实波形 */ function drawRealWaveform(signals) { if (!signals || signals.length === 0) { return \` 无波形数据 \`; } const svgWidth = 800; const svgHeight = Math.max(80, signals.length * 30 + 20); const signalHeight = 20; const signalSpacing = 30; const leftMargin = 80; const rightMargin = 20; const waveformWidth = svgWidth - leftMargin - rightMargin; const colors = ['var(--vscode-charts-blue)', 'var(--vscode-charts-green)', 'var(--vscode-charts-orange)']; let svgContent = \`\`; // 绘制每个信号 signals.forEach((signal, index) => { const y = 10 + index * signalSpacing; const color = colors[index % colors.length]; // 绘制信号名称 svgContent += \`\${signal.name}\`; // 如果没有值变化数据,显示提示 if (!signal.values || signal.values.length === 0) { svgContent += \`无数据\`; return; } // 计算时间范围 const times = signal.values.map(v => v.time); const minTime = Math.min(...times); const maxTime = Math.max(...times); const timeRange = maxTime - minTime || 1; // 绘制波形 if (signal.width === 1) { // 单比特信号 - 绘制数字波形 let pathData = ''; const yHigh = y; const yLow = y + signalHeight; signal.values.forEach((point, i) => { const x = leftMargin + ((point.time - minTime) / timeRange) * waveformWidth; const currentY = (point.value === '1') ? yHigh : yLow; if (i === 0) { pathData = \`M \${x} \${currentY}\`; } else { const prevValue = signal.values[i - 1].value; const prevY = (prevValue === '1') ? yHigh : yLow; if (prevY !== currentY) { pathData += \` L \${x} \${prevY} L \${x} \${currentY}\`; } else { pathData += \` L \${x} \${currentY}\`; } } }); // 延伸到右边界 const lastValue = signal.values[signal.values.length - 1].value; const lastY = (lastValue === '1') ? yHigh : yLow; pathData += \` L \${leftMargin + waveformWidth} \${lastY}\`; svgContent += \`\`; } else { // 多比特信号 - 绘制总线波形(上下双线) const yTop = y + 5; const yBottom = y + signalHeight - 5; const transitionWidth = 4; let topPath = \`M \${leftMargin} \${yTop}\`; let bottomPath = \`M \${leftMargin} \${yBottom}\`; signal.values.forEach((point, i) => { const x = leftMargin + ((point.time - minTime) / timeRange) * waveformWidth; // 上线和下线都延伸到变化点 topPath += \` L \${x} \${yTop}\`; bottomPath += \` L \${x} \${yBottom}\`; // 绘制梯形过渡 topPath += \` L \${x + transitionWidth} \${yBottom} L \${x + transitionWidth} \${yTop}\`; bottomPath += \` L \${x + transitionWidth} \${yTop} L \${x + transitionWidth} \${yBottom}\`; }); // 延伸到右边界 topPath += \` L \${leftMargin + waveformWidth} \${yTop}\`; bottomPath += \` L \${leftMargin + waveformWidth} \${yBottom}\`; svgContent += \`\`; svgContent += \`\`; } }); // 绘制时间轴 const timeAxisY = svgHeight - 5; svgContent += \`\`; svgContent += \`\`; return svgContent; } /** * 打开完整波形查看器(在新列中) */ function openFullWaveform(vcdFilePath) { vscode.postMessage({ command: 'openWaveformViewer', vcdFilePath: vcdFilePath }); } /** * 在消息中添加波形预览 */ function addWaveformPreviewToMessage(messageDiv, vcdFilePath, fileName) { const preview = createWaveformPreview(vcdFilePath, fileName); messageDiv.appendChild(preview); } `; }