Appearance
Spec: Tabbed Multi-Document Interface
Overview
Add support for opening and working on multiple circuits simultaneously using a tabbed interface, enabling rapid switching between related circuits and macro definitions.
Motivation
Real projects often involve multiple related circuit files — a top-level design, macro sub-circuits, testbenches, and library components. Currently, users must close one file to open another, losing context. Tabs allow parallel work and quick reference across files.
Requirements
Functional Requirements
- Tab Bar: Horizontal tab bar showing all open circuits, each with filename and close button.
- Multiple Open Files: Open unlimited circuit files simultaneously (memory-permitting).
- Tab Switching: Click tab to switch, Ctrl+Tab to cycle, Ctrl+1-9 for specific tabs.
- Close Tab: Close individual tabs with middle-click or X button.
- Dirty Indicator: Modified/unsaved tabs show a dot or asterisk indicator.
- New Tab: Ctrl+N creates a new empty circuit in a new tab.
- Tab Reordering: Drag tabs to reorder.
- Tab Overflow: When tabs exceed space, show a dropdown or scroll arrows.
- Context Menu: Right-click tab for options (Close, Close Others, Close All, Copy Path).
- Independent State: Each tab maintains its own zoom, scroll position, selection, and editor mode.
- Shared Simulation: Option to simulate all open circuits or just the active tab.
- Open Macro in Tab: Double-click a macro component to open its definition in a new tab.
- Tab Persistence: Remember open tabs across application sessions (restore on startup).
Non-Functional Requirements
- Tab switching is instant (< 50ms) — canvas state is preserved in memory.
- Memory usage scales linearly with open circuits.
- No performance impact on inactive tabs.
Design
Architecture
csharp
public class DocumentManager
{
public ObservableCollection<CircuitDocument> OpenDocuments { get; }
public CircuitDocument ActiveDocument { get; set; }
public CircuitDocument OpenFile(string path);
public CircuitDocument CreateNew();
public void CloseDocument(CircuitDocument doc);
public bool HasUnsavedChanges { get; }
}
public class CircuitDocument
{
public string FilePath { get; }
public string DisplayName { get; } // filename or "Untitled N"
public Circuit Circuit { get; }
public bool IsDirty { get; }
public EditorState EditorState { get; } // zoom, scroll, selection, mode
public UndoStack UndoStack { get; } // per-document undo
}UI Layout
┌─────────────────────────────────────────────┐
│ [Tab1] [Tab2*] [Tab3] [+] [▼ overflow] │
├─────────────────────────────────────────────┤
│ │
│ Canvas Area │
│ (active document) │
│ │
└─────────────────────────────────────────────┘Tab Rendering
- Active tab: elevated/highlighted with accent color.
- Inactive tabs: subtle background.
- Dirty tab: filename suffixed with ● or bolded.
- Tab shows file icon + filename (truncated if long).
Session Persistence
json
// Saved to app settings
{
"openTabs": [
{ "path": "C:\\circuits\\cpu.dwm", "isActive": true },
{ "path": "C:\\circuits\\alu.dwm", "isActive": false }
]
}Implementation Tasks
- Create
DocumentManagerclass to manage open documents. - Create
CircuitDocumentclass wrapping Circuit + editor state. - Implement tab bar UI control (WinUI TabView or custom).
- Implement tab switching with state preservation.
- Move per-document state (undo stack, zoom, selection) into
CircuitDocument. - Implement dirty tracking per document.
- Add keyboard shortcuts (Ctrl+Tab, Ctrl+W, Ctrl+N, Ctrl+1-9).
- Implement tab context menu (Close, Close Others, Close All).
- Implement "Open Macro in Tab" navigation.
- Add session persistence (remember open tabs across restarts).
- Update window title to show active document name.
Risks & Open Questions
- Memory impact of keeping many large circuits in memory simultaneously?
- Should inactive tabs keep their canvas rendered or regenerate on switch?
- How do shared resources (toolbox, properties panel) update when switching tabs?
- Should there be a limit on open tabs, or leave it to system resources?
Priority
Medium-High — Standard modern application feature, expected by users.