import { TerminalView } from './terminal-view.js'; export class TabSplitTree { constructor(options = {}) { this.container = options.container; this.tabId = options.tabId; this.onActiveTerminalChange = options.onActiveTerminalChange || (() => {}); this.onEmpty = options.onEmpty || (() => {}); this.onTitleChange = options.onTitleChange || (() => {}); this.terminals = new Map(); // id -> TerminalView this.activeTerminal = null; this.rootElement = document.createElement('div'); this.rootElement.className = 'split-container horizontal'; this.container.appendChild(this.rootElement); // 创建初始窗格 this.addPane(this.rootElement); } addPane(parentElement, orientation = 'horizontal') { const paneElement = document.createElement('div'); paneElement.className = 'split-pane'; parentElement.appendChild(paneElement); const termView = new TerminalView({ container: paneElement, onFocus: (term) => { this.setActiveTerminal(term); }, onTitleChange: (title) => { if (this.activeTerminal === termView) { this.onTitleChange(title); } }, onExit: () => { this.closeTerminal(termView.id); }, }); this.terminals.set(termView.id, { termView, paneElement, parentElement, }); paneElement.addEventListener('click', () => { termView.focus(); }); this.setActiveTerminal(termView); return termView; } splitCurrent(direction = 'horizontal') { if (!this.activeTerminal) return; const currentInfo = this.terminals.get(this.activeTerminal.id); if (!currentInfo) return; const currentPane = currentInfo.paneElement; const parent = currentPane.parentElement; // 创建一个新的 split-container 容器替换原有 pane,实现嵌套分屏 const splitWrapper = document.createElement('div'); splitWrapper.className = `split-container ${direction}`; parent.replaceChild(splitWrapper, currentPane); splitWrapper.appendChild(currentPane); // 添加分割线 const divider = document.createElement('div'); divider.className = 'split-divider'; splitWrapper.appendChild(divider); // 添加新窗格 const newTerm = this.addPane(splitWrapper, direction); // 刷新自适应尺寸 setTimeout(() => { this.fitAll(); newTerm.focus(); }, 50); } setActiveTerminal(termView) { this.activeTerminal = termView; // 清除所有聚焦样式 for (const info of this.terminals.values()) { info.paneElement.classList.remove('focused'); } const currentInfo = this.terminals.get(termView.id); if (currentInfo) { currentInfo.paneElement.classList.add('focused'); } this.onActiveTerminalChange(termView); this.onTitleChange(termView.title); } closeTerminal(termId) { const info = this.terminals.get(termId); if (!info) return; info.termView.destroy(); const pane = info.paneElement; const parent = pane.parentElement; this.terminals.delete(termId); pane.remove(); if (this.terminals.size === 0) { this.onEmpty(); return; } // 焦点转移给另一个终端 const nextTerm = this.terminals.values().next().value.termView; this.setActiveTerminal(nextTerm); nextTerm.focus(); this.fitAll(); } fitAll() { for (const info of this.terminals.values()) { info.termView.fit(); } } destroy() { for (const info of this.terminals.values()) { info.termView.destroy(); } this.terminals.clear(); this.rootElement.remove(); } }