Skip to content

Lift TUI + GTK rasterisers out of vimcode and into the quadraui crate #223

Description

@JDonaghy

Summary

vimcode keeps its primitive rasterisers (`quadraui_tui::draw_` in `src/tui_main/`, `quadraui_gtk::draw_` in `src/gtk/`) private to the vimcode crate. That means every external consumer of `quadraui` — `kubeui` today, the SQL client (#46), the k8s dashboard tracking issue (#145), any future Lua-plugin-driven app via #146 — has to reimplement `draw_list`, `draw_status_bar`, `draw_tree`, `draw_palette`, etc. from scratch.

This is the single biggest gap between what quadraui delivers today and what its design promise claims.

Evidence from the kubeui spike (just merged on develop, #145)

Three workspace crates ended up at:

Crate Lines What
`kubeui-core` (lib) 910 state + k8s + view-builders + Action reducer — fully shared
`kubeui` (TUI bin) 494 crossterm + ratatui rasterisers + KeyCode→Action map
`kubeui-gtk` (GTK bin) 502 gtk4 + Cairo/Pango rasterisers + gdk::Key→Action map

Code sharing: ~65%. The TUI and GTK binaries are structurally identical (same `paint` flow, same modal precedence, same primitive consumption) but each contains ~300 lines of rasterisation that mirrors what `src/tui_main/quadraui_tui.rs` and `src/gtk/quadraui_gtk.rs` already do, just slightly differently.

Pushing the rasterisers into quadraui takes that to ~90%.

Proposal

Create new modules inside the quadraui crate:

```
quadraui/
├── src/
│ ├── lib.rs
│ ├── primitives/ ← already exists
│ ├── tui/ ← NEW — public ratatui rasterisers
│ │ ├── mod.rs
│ │ ├── list.rs
│ │ ├── tree.rs
│ │ ├── palette.rs
│ │ ├── status_bar.rs
│ │ └── tab_bar.rs
│ └── gtk/ ← NEW — public Cairo + Pango rasterisers
│ ├── mod.rs
│ ├── list.rs
│ ├── tree.rs
│ ├── palette.rs
│ ├── status_bar.rs
│ └── tab_bar.rs
└── Cargo.toml ← gate each on a feature
```

Feature gates (matches the existing `gtk-example` precedent):

```toml
[features]
tui = ["dep:ratatui"]
gtk = ["dep:gtk4", "dep:pangocairo"]

[dependencies]
ratatui = { version = "0.29", optional = true }
gtk4 = { version = "0.7", optional = true, features = ["v4_10"] }
pangocairo = { version = "0.18", optional = true }
```

Pure-data primitives stay default-feature (no bloat for consumers that only use the data layer). Apps that want the TUI rasterisers enable `tui`; apps that want the GTK rasterisers enable `gtk`. Vimcode enables both.

Rasterisers should take a backend-agnostic theme handle (a `Theme` struct or trait) so consumers can supply their own colour scheme rather than vimcode's hardcoded one.

Migration plan

  1. Pilot: pick one primitive (`StatusBar` or `TabBar` — already on D6) and lift just that pair (TUI + GTK) into quadraui. Add tests.
  2. Vimcode adopts: replace `src/tui_main/quadraui_tui.rs::draw_status_bar` and `src/gtk/quadraui_gtk.rs::draw_status_bar` with re-exports from `quadraui::tui::draw_status_bar` etc. Existing private helpers stay until the next primitive is migrated.
  3. kubeui adopts: drop `kubeui::draw_status_bar` in both backends, call the quadraui-provided version directly.
  4. Iterate primitive by primitive: `ListView`, `TreeView`, `Palette`, `Form`, `Tooltip`, `Dialog`, `ContextMenu`. Each migration is a per-primitive commit, vimcode + kubeui both gain the move-up at the same time.
  5. Cleanup: once all primitives are migrated, vimcode's `src/tui_main/quadraui_tui.rs` and `src/gtk/quadraui_gtk.rs` shrink to pass-throughs and can be deleted.

Tradeoffs

  • + External apps stop reimplementing. Bug fixes in rasterisers go to one place. Adding a third backend (Win-GUI) means writing one set of rasterisers, not N.
  • + Vimcode's GTK + TUI rewrites (Phase B.5–B.6) become smaller — they consume quadraui rasterisers instead of carrying their own private set.
  • - Theme handling needs to generalise. Vimcode's `Theme` is rich (LSP semantic colours, git diff colours, …) but that's specific to a code editor. Quadraui's primitives only need a small surface (bg, fg, accent, border, etc.). Likely outcome: quadraui defines a small `Theme` struct, vimcode and kubeui each populate it from their own theme systems.
  • - Versioning friction — once rasterisers are public, primitive layout changes can break consumers' visual output. Existing Phase B.4 already exposes `*Layout` types; raster surface is similar.

Why this is a v1 priority

The k8s dashboard tracking issue (#145) is explicit:

The point isn't the dashboard — it's exercising quadraui from outside vimcode to see what's awkward.

The kubeui spike answered "what's awkward": rasterisers are private. Every other awkwardness was minor — types had `underline: false` extra fields, `StatusBarSegment` had no `width_cells`, etc. — and those are documentation issues. This is structural.

Files

  • New: `quadraui/src/tui/`, `quadraui/src/gtk/` (per-primitive rasteriser modules)
  • New: `quadraui/src/theme.rs` (small backend-agnostic Theme struct)
  • Modified: `quadraui/Cargo.toml` (feature gates)
  • Modified: `src/tui_main/quadraui_tui.rs` and `src/gtk/quadraui_gtk.rs` (vimcode-side adoption, primitive by primitive)
  • Modified: `kubeui/src/main.rs` and `kubeui-gtk/src/main.rs` (drop reimplemented rasterisers)

Surfaced by

The kubeui validation spike on develop (`1cbc98b`).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions