import Cocoa class MainWindowController: NSWindowController { var tabManager = TabManager() var tabBar: NSStackView! var contentView: NSView! var currentSessionView: NSScrollView? convenience init() { let window = NSWindow( contentRect: NSRect(x: 0, y: 0, width: 1000, height: 700), styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView], backing: .buffered, defer: false ) window.titlebarAppearsTransparent = true window.titleVisibility = .hidden window.center() window.title = "Enhanced Terminal" window.isReleasedWhenClosed = false self.init(window: window) setupUI() addNewTab() // Force window to show window.makeKeyAndOrderFront(nil) window.orderFrontRegardless() } private func setupUI() { guard let window = window else { return } let mainContainer = NSView(frame: window.contentView!.bounds) mainContainer.autoresizingMask = [.width, .height] // Tab bar tabBar = NSStackView(frame: NSRect(x: 0, y: mainContainer.bounds.height - 40, width: mainContainer.bounds.width, height: 40)) tabBar.orientation = .horizontal tabBar.distribution = .fillProportionally tabBar.spacing = 0 tabBar.autoresizingMask = [.width, .minYMargin] tabBar.wantsLayer = true tabBar.layer?.backgroundColor = NSColor(white: 0.15, alpha: 1.0).cgColor // Content view contentView = NSView(frame: NSRect(x: 0, y: 0, width: mainContainer.bounds.width, height: mainContainer.bounds.height - 40)) contentView.autoresizingMask = [.width, .height] mainContainer.addSubview(contentView) mainContainer.addSubview(tabBar) window.contentView = mainContainer setupMenuBar() } private func setupMenuBar() { let mainMenu = NSMenu() // App menu let appMenuItem = NSMenuItem() mainMenu.addItem(appMenuItem) let appMenu = NSMenu() appMenuItem.submenu = appMenu appMenu.addItem(NSMenuItem(title: "Settings...", action: #selector(openSettings), keyEquivalent: ",")) appMenu.addItem(NSMenuItem.separator()) appMenu.addItem(NSMenuItem(title: "Quit", action: #selector(NSApplication.terminate(_:)), keyEquivalent: "q")) // File menu let fileMenuItem = NSMenuItem(title: "File", action: nil, keyEquivalent: "") mainMenu.addItem(fileMenuItem) let fileMenu = NSMenu(title: "File") fileMenuItem.submenu = fileMenu fileMenu.addItem(NSMenuItem(title: "New Tab", action: #selector(addNewTab), keyEquivalent: "t")) fileMenu.addItem(NSMenuItem(title: "Close Tab", action: #selector(closeCurrentTab), keyEquivalent: "w")) fileMenu.addItem(NSMenuItem.separator()) fileMenu.addItem(NSMenuItem(title: "Split Vertically", action: #selector(splitVertically), keyEquivalent: "d")) let splitHorizontal = NSMenuItem(title: "Split Horizontally", action: #selector(splitHorizontally), keyEquivalent: "d") splitHorizontal.keyEquivalentModifierMask = [.command, .shift] fileMenu.addItem(splitHorizontal) // Edit menu let editMenuItem = NSMenuItem(title: "Edit", action: nil, keyEquivalent: "") mainMenu.addItem(editMenuItem) let editMenu = NSMenu(title: "Edit") editMenuItem.submenu = editMenu editMenu.addItem(NSMenuItem(title: "Copy", action: #selector(NSText.copy(_:)), keyEquivalent: "c")) editMenu.addItem(NSMenuItem(title: "Paste", action: #selector(NSText.paste(_:)), keyEquivalent: "v")) editMenu.addItem(NSMenuItem(title: "Select All", action: #selector(NSText.selectAll(_:)), keyEquivalent: "a")) editMenu.addItem(NSMenuItem.separator()) editMenu.addItem(NSMenuItem(title: "Search History", action: #selector(searchHistory), keyEquivalent: "r")) // View menu let viewMenuItem = NSMenuItem(title: "View", action: nil, keyEquivalent: "") mainMenu.addItem(viewMenuItem) let viewMenu = NSMenu(title: "View") viewMenuItem.submenu = viewMenu viewMenu.addItem(NSMenuItem(title: "Toggle Fullscreen", action: #selector(NSWindow.toggleFullScreen(_:)), keyEquivalent: "f")) viewMenu.addItem(NSMenuItem(title: "Increase Font Size", action: #selector(increaseFontSize), keyEquivalent: "+")) viewMenu.addItem(NSMenuItem(title: "Decrease Font Size", action: #selector(decreaseFontSize), keyEquivalent: "-")) // Tools menu let toolsMenuItem = NSMenuItem(title: "Tools", action: nil, keyEquivalent: "") mainMenu.addItem(toolsMenuItem) let toolsMenu = NSMenu(title: "Tools") toolsMenuItem.submenu = toolsMenu toolsMenu.addItem(NSMenuItem(title: "AI Command Generator", action: #selector(showAIGenerator), keyEquivalent: "k")) toolsMenu.addItem(NSMenuItem(title: "Snippets", action: #selector(showSnippets), keyEquivalent: "p")) toolsMenu.addItem(NSMenuItem(title: "Command Palette", action: #selector(showCommandPalette), keyEquivalent: "p")) NSApp.mainMenu = mainMenu } @objc func addNewTab() { let session = tabManager.addTab() session.setupTextView(frame: contentView.bounds) session.startShell() updateTabBar() switchToTab(index: tabManager.tabs.count - 1) } @objc func closeCurrentTab() { guard tabManager.tabs.count > 1 else { NSApp.terminate(nil) return } tabManager.removeTab(at: tabManager.currentIndex) updateTabBar() switchToTab(index: tabManager.currentIndex) } private func updateTabBar() { tabBar.arrangedSubviews.forEach { $0.removeFromSuperview() } for (index, session) in tabManager.tabs.enumerated() { let tabButton = NSButton(frame: NSRect(x: 0, y: 0, width: 150, height: 40)) tabButton.title = session.title tabButton.bezelStyle = .rounded tabButton.tag = index tabButton.target = self tabButton.action = #selector(tabClicked(_:)) if index == tabManager.currentIndex { tabButton.contentTintColor = .systemBlue } tabBar.addArrangedSubview(tabButton) } // Add new tab button let newTabButton = NSButton(frame: NSRect(x: 0, y: 0, width: 40, height: 40)) newTabButton.title = "+" newTabButton.bezelStyle = .rounded newTabButton.target = self newTabButton.action = #selector(addNewTab) tabBar.addArrangedSubview(newTabButton) } @objc func tabClicked(_ sender: NSButton) { switchToTab(index: sender.tag) } private func switchToTab(index: Int) { guard index < tabManager.tabs.count else { return } tabManager.selectTab(at: index) contentView.subviews.forEach { $0.removeFromSuperview() } if let session = tabManager.getCurrentSession(), let scrollView = session.textView.enclosingScrollView { scrollView.frame = contentView.bounds contentView.addSubview(scrollView) currentSessionView = scrollView } updateTabBar() } @objc func splitVertically() { showAlert("Split panes feature coming soon!") } @objc func splitHorizontally() { showAlert("Split panes feature coming soon!") } @objc func searchHistory() { let panel = HistorySearchPanel() panel.show(relativeTo: window!) { [weak self] command in if let command = command, let session = self?.tabManager.getCurrentSession() { session.textView.insertText(command, replacementRange: NSRange(location: session.textView.string.count, length: 0)) } } } @objc func showSnippets() { let panel = SnippetPanel() panel.show(relativeTo: window!) { [weak self] snippet in if let snippet = snippet, let session = self?.tabManager.getCurrentSession() { session.textView.insertText(snippet.command, replacementRange: NSRange(location: session.textView.string.count, length: 0)) } } } @objc func showAIGenerator() { guard AIManager.shared.isAvailable() else { showAlert("Please configure AI provider in Settings first") return } let panel = AIGeneratorPanel() panel.show(relativeTo: window!) { [weak self] command in if let command = command, let session = self?.tabManager.getCurrentSession() { session.textView.insertText(command, replacementRange: NSRange(location: session.textView.string.count, length: 0)) } } } @objc func showCommandPalette() { showAlert("Command palette coming soon!") } @objc func openSettings() { let settingsWindow = SettingsWindowController() settingsWindow.showWindow(nil) } @objc func increaseFontSize() { TerminalSettings.shared.fontSize += 1 tabManager.tabs.forEach { $0.applyTheme() } } @objc func decreaseFontSize() { TerminalSettings.shared.fontSize = max(8, TerminalSettings.shared.fontSize - 1) tabManager.tabs.forEach { $0.applyTheme() } } private func showAlert(_ message: String) { let alert = NSAlert() alert.messageText = message alert.alertStyle = .informational alert.addButton(withTitle: "OK") alert.runModal() } }