Skip to content

Commit 9709e06

Browse files
committed
Update comparison.md
1 parent 8840214 commit 9709e06

1 file changed

Lines changed: 91 additions & 0 deletions

File tree

docs/COMPARISON.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,4 +338,95 @@ This gives you Spectre's polished formatting with SharpConsoleUI's window manage
338338

339339
---
340340

341+
## Rendering Architecture Deep Dive
342+
343+
TUI frameworks differ most fundamentally in how they turn a tree of controls into pixels on screen. This section explains where SharpConsoleUI sits and why the differences matter.
344+
345+
### How TUI Frameworks Render
346+
347+
| Approach | Description | Used by |
348+
|---|---|---|
349+
| **String output** | `View()` returns a string; framework diffs strings | BubbleTea (Go) |
350+
| **Immediate-mode** | Redraw entire UI into a single buffer each frame | Ratatui (Rust) |
351+
| **Retained-mode, shared buffer** | Widget tree paints into one buffer with dirty tracking | Textual (Python), Terminal.Gui (.NET) |
352+
| **Retained-mode, per-window buffers** | Each window has its own buffer; a compositor merges them | SharpConsoleUI (.NET) |
353+
354+
Most TUI frameworks use a single shared buffer. SharpConsoleUI gives each window its own `CharacterBuffer`, then composites them together -- a pattern borrowed from desktop window managers (DWM, Quartz, Wayland compositors), adapted for character cells.
355+
356+
### The Compositor Pipeline
357+
358+
```
359+
Per-Window Buffers Compositor Console Driver
360+
┌──────────┐
361+
│ Window A │──┐
362+
└──────────┘ │ ┌──────────────────┐ ┌─────────────────┐
363+
┌──────────┐ ├──▶│ Visible Regions │──▶│ Diff-based flush│──▶ stdout
364+
│ Window B │──┤ │ (skip occluded) │ │ (changed cells) │
365+
└──────────┘ │ └──────────────────┘ └─────────────────┘
366+
┌──────────┐ │
367+
│ Overlay │──┘
368+
└──────────┘
369+
```
370+
371+
The visible regions calculator uses rectangle subtraction to determine which pixels of each window are actually visible on screen. Occluded regions are skipped entirely rather than painted and overwritten.
372+
373+
Each window's render also supports compositor hooks: `PreBufferPaint` fires before controls (for gradients, custom backgrounds), then controls paint, then `PostBufferPaint` fires (for effects like blur or fade).
374+
375+
### Frame-Coupled Animations
376+
377+
The animation system runs inside the main render loop, not on separate timers:
378+
379+
1. Poll input
380+
2. Advance animations (`AnimationManager.Update(deltaTime)`)
381+
3. Layout pass (Measure → Arrange → Paint)
382+
4. Composite and flush
383+
384+
Delta time is capped at 33ms to prevent animations from completing instantly after idle periods. This is what enables smooth transitions in controls like NavigationView -- the animation and layout run in the same frame tick.
385+
386+
### DOM Layout
387+
388+
SharpConsoleUI uses a three-pass DOM layout (Measure → Arrange → Paint) similar to WPF and Avalonia. Each control reports its desired size, receives its final bounds from its parent, then paints into its window buffer. This is what allows the responsive NavigationView to detect its actual width and switch display modes.
389+
390+
---
391+
392+
## Cross-Ecosystem Comparison
393+
394+
Different languages have their own established TUI frameworks. Here's how the major ones compare architecturally.
395+
396+
### Feature Comparison
397+
398+
| | SharpConsoleUI | Textual | Ratatui | BubbleTea | Terminal.Gui |
399+
|---|---|---|---|---|---|
400+
| **Language** | C# | Python | Rust | Go | C# |
401+
| **Architecture** | Compositor | Retained + segment compositor | Immediate-mode | Elm (TEA) | Retained, shared buffer |
402+
| **Overlapping windows** | Yes | Screens (modal stack) | No | No | v2 beta |
403+
| **Window management** | Drag, resize, minimize, maximize | No | No | No | v2 beta |
404+
| **Built-in animations** | Frame-coupled tweens | CSS-like transitions | Via tachyonfx crate | No | No |
405+
| **Overlay/portal system** | Yes (auto-positioning, auto-dismiss) | Screen stack | Manual | Manual | No |
406+
| **Responsive controls** | Yes (NavigationView) | CSS-like media queries | No | No | No |
407+
| **Per-window buffers** | Yes | No | No | No | No |
408+
| **Compositor hooks** | PreBufferPaint / PostBufferPaint | No | No | No | No |
409+
| **DOM layout pipeline** | Measure / Arrange / Paint | CSS Box Model | Constraint-based | String concat | Pos/Dim arithmetic |
410+
| **Async per-window** | Yes | Async workers | Manual | Goroutines | No |
411+
| **Desktop packaging** | schost | textual-web (browser) | No | No | No |
412+
| **Embedded terminal** | PTY-backed | No | No | No | No |
413+
| **Mouse** | Full | Full | Via backend | Via backend | Full |
414+
| **24-bit color** | Yes | Yes | Yes | Via Lip Gloss | Yes |
415+
416+
### How They Differ
417+
418+
**Ratatui** is a lightweight Rust library where you own the event loop and redraw the entire UI each frame. Clean and fast, but no retained state or compositing -- you manage everything yourself.
419+
420+
**BubbleTea** uses the Elm architecture in Go -- your `View()` returns a string, the framework diffs it. Elegant for single-screen apps. The string-based model doesn't support pixel-level compositing.
421+
422+
**Textual** has its own segment-based compositor that merges overlapping widget output. It uses a spatial grid for fast hit-testing and supports CSS-like animations and styling. The most feature-rich Python TUI framework.
423+
424+
**Terminal.Gui** is the most mature .NET TUI library with the widest control set. v2 (beta) adds overlapping window support. Uses a shared buffer with painter's algorithm rendering.
425+
426+
**SharpConsoleUI** takes the compositor approach further with per-window buffers, occlusion culling via rectangle subtraction, and compositor hooks for visual effects. The animation system and DOM layout pipeline enable features like the responsive NavigationView with animated mode transitions.
427+
428+
Each framework makes different tradeoffs. The compositor approach adds complexity but enables desktop-class features (window management, visual effects, animated responsive controls) that are difficult to achieve with a shared buffer or string-based model.
429+
430+
---
431+
341432
*Last updated: March 2026*

0 commit comments

Comments
 (0)