Add Layout, Text, and Fonts

In this step, the simple panel evolves into a small dashboard layout. We introduce multiple framed areas, wrapped text blocks, Unicode content, and an animated bitmap-font headline.

These features demonstrate how the library can be used to build structured terminal interfaces without implementing a custom layout system.

Replace signal-board/src/main.cpp

Update the source file with the following version:

<project>/signal-board/src/main.cpp
#include <erbsland/cterm/all.hpp>

using namespace erbsland::cterm;

auto main() -> int {
    auto terminal = Terminal{Size{96, 28}};
    terminal.initializeScreen();

    auto buffer = Buffer{terminal.size()};
    buffer.fill(Char{" ", Color{fg::Default, bg::Black}});

    const auto canvas = Rectangle{0, 0, buffer.size().width(), buffer.size().height()};
    const auto titleRect = canvas.subRectangle(Anchor::TopCenter, Size{0, 6}, Margins{1, 2, 0, 2});
    const auto bodyRect = canvas.insetBy(Margins{7, 2, 2, 2});
    const auto leftRect = bodyRect.subRectangle(Anchor::Left, Size{bodyRect.width() / 2 - 1, 0}, Margins{0});
    const auto rightRect = bodyRect.subRectangle(Anchor::Right, Size{bodyRect.width() / 2 - 1, 0}, Margins{0});

    auto title = Text{String{"COLOR TERM"}, titleRect, Alignment::Center};
    title.setFont(Font::defaultAscii());
    title.setColorSequence(ColorSequence{
        {Color{fg::BrightBlue, bg::Black}, 3},
        {Color{fg::BrightCyan, bg::Black}, 3},
        {Color{fg::BrightMagenta, bg::Black}, 3},
        {Color{fg::BrightYellow, bg::Black}, 3},
        {Color{fg::BrightGreen, bg::Black}, 3},
    });
    title.setAnimation(TextAnimation::ColorDiagonal);
    buffer.drawText(title, 12);

    buffer.drawFilledFrame(
        leftRect,
        FrameStyle::LightWithRoundedCorners,
        Char{" ", bg::BrightBlack});
    buffer.drawText(
        "Wrapped Text",
        Rectangle{leftRect.x1() + 2, leftRect.y1(), leftRect.width() - 4, 1},
        Alignment::Center,
        Color{fg::BrightWhite, bg::BrightBlack});
    buffer.drawText(
        "The library wraps text inside rectangles, so panels stay readable without a custom layout engine.",
        Rectangle{leftRect.x1() + 1, leftRect.y1() + 2, leftRect.width() - 2, leftRect.height() - 3},
        Alignment::TopLeft,
        Color{fg::BrightWhite, bg::BrightBlack});

    buffer.drawFilledFrame(
        rightRect,
        FrameStyle::Double,
        Char{" ", bg::Blue});
    buffer.drawText(
        "Unicode Width",
        Rectangle{rightRect.x1() + 2, rightRect.y1(), rightRect.width() - 4, 1},
        Alignment::Center,
        Color{fg::BrightWhite, bg::Blue});
    buffer.drawText(
        "Zürich, café, 東京, 漢字, and ASCII stay aligned because the renderer measures terminal cell width.",
        Rectangle{rightRect.x1() + 1, rightRect.y1() + 2, rightRect.width() - 2, rightRect.height() - 3},
        Alignment::Center,
        Color{fg::BrightWhite, bg::Blue});

    auto settings = UpdateSettings{};
    settings.setSwitchToAlternateBuffer(false);
    terminal.updateScreen(buffer, settings);
    terminal.flush();
    terminal.restoreScreen();
    return 0;
}

Features Introduced in This Step

This version combines several important layout and text-rendering features:

  • Rectangle::subRectangle() and Rectangle::insetBy() help derive smaller layout regions from a larger canvas.

  • Text stores the content together with its layout rectangle, alignment, font, color sequence, and animation settings.

  • Font::defaultAscii() renders large bitmap text directly in the terminal.

  • ColorSequence and TextAnimation make animated titles or highlights easy to implement.

  • Wrapped Unicode text remains visually aligned even when mixing characters with different terminal widths.

  • UpdateSettings can keep a short-lived rendered example on the main screen by disabling alternate-screen switching.

../../_images/text-gallery1.jpg

The text-gallery demo expands on the same text, Unicode, and bitmap-font features used in this step.

Add Input and a Redraw Loop →