Skip to content

Add SpectreView — render any Spectre.Console IRenderable inside a Terminal.Gui app #5392

@tig

Description

@tig

Summary

Create a SpectreView class — a Terminal.Gui View that renders any Spectre.Console IRenderable inside a TG application. This allows developers to embed Spectre's rich static widgets (Table, Panel, Tree, Rule, BarChart, Calendar, FigletText, JsonText) as read-only decorative elements in an interactive TG window.

Motivation

Developers using Spectre.Console have beautiful Table/Panel/Tree widgets for stdout output. When they build an interactive TG app, they lose access to those widgets. SpectreView bridges this gap: drop a Spectre renderable into any TG layout and it just works.

Proposed API

namespace Terminal.Gui.Interop.Spectre;

public class SpectreView : View
{
    /// Gets or sets the Spectre renderable to display.
    public IRenderable? Renderable { get; set; }

    /// Gets or sets whether the view auto-sizes to content.
    public bool AutoSize { get; set; } = true;

    protected override bool OnDrawingContent (DrawContext? context)
    {
        if (Renderable is null) return true;

        // 1. Measure the renderable at viewport width
        int maxWidth = Viewport.Width;

        // 2. Render to Spectre Segments
        IEnumerable<Segment> segments = Renderable.Render (renderOptions, maxWidth);

        // 3. Convert Spectre Segments to TG drawing calls
        int col = 0, row = 0;
        foreach (Segment segment in segments)
        {
            if (segment.IsLineBreak) { row++; col = 0; continue; }
            SetAttribute (segment.Style.ToAttribute ());
            Move (col, row);
            AddStr (segment.Text);
            col += segment.Text.GetColumns ();
        }
        return true;
    }
}

Usage

// Embed a Spectre Table inside a TG window
Table spectreTable = new Table ()
    .AddColumn ("Name")
    .AddColumn ("Score")
    .AddRow ("Alice", "100")
    .Border (TableBorder.Rounded);

SpectreView tableView = new ()
{
    Renderable = spectreTable,
    X = 0, Y = 0,
    Width = Dim.Fill (),
    Height = Dim.Auto (DimAutoStyle.Content)
};
window.Add (tableView);

Design Decisions

  • SpectreView is read-only display only — it does NOT make Spectre widgets interactive (no scroll, no focus, no selection)
  • For interactive data, devs should use TG's native TableView, TreeView, ListView
  • For static/decorative display (panels, rules, bar charts, figlet text, JSON), SpectreView is perfect
  • Setting Renderable to a new value triggers a redraw
  • Uses Dim.Auto(DimAutoStyle.Content) to auto-size height based on rendered content
  • Must handle Spectre's Segment.IsLineBreak and Segment.IsWhiteSpace correctly
  • Must convert Spectre Style to TG Attribute using the converters from the bridge package

When to Use SpectreView vs Native TG Views

Widget Use SpectreView Use TG Native
Table (read-only display) Yes No
Table (interactive, scrollable) No Yes - TableView
Tree (static display) Yes No
Tree (interactive, expandable) No Yes - TreeView<T>
Panel / Rule / FigletText Yes (decorative) N/A
BarChart / Calendar Yes N/A
JSON display Yes (JsonText) Yes (MarkdownCodeBlock)
Rich Markdown No Yes - Markdown view

Acceptance Criteria

  • SpectreView : View in Terminal.Gui.Interop.Spectre project
  • Renders any IRenderable by measuring + rendering to Segments + converting to TG draw calls
  • Correctly handles line breaks, whitespace, and multi-line renderables
  • Style conversion uses SpectreMarkupBridge.ToAttribute() (from issue Add Terminal.Gui.Interop.Spectre bridge package with Markup parsing and Style conversion #5391)
  • Supports Dim.Auto(DimAutoStyle.Content) by reporting content size from measurement
  • Re-renders when Renderable property changes
  • AOT-compatible (no reflection)
  • Unit tests: Table, Panel, Rule, FigletText, Tree, BarChart rendered correctly
  • Integration test: SpectreView embedded in a TG Window with other interactive Views

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions