Frames, Borders, Tiles

The drawing types define how frames, borders, filled areas, and character combinations are rendered into writable buffers.

They form the foundation for panels, boxes, separators, decorative borders, tiled backgrounds, and line-art style layouts.

Details about the example output on this page

The examples below were rendered with the dedicated documentation helper doc/tools/drawing-reference.cpp at a fixed width of 70 terminal columns. This makes it easy to regenerate the visual output together with the code snippets.

Usage

Filling Panels and Drawing Simple Frames

WritableBuffer provides convenient functions to fill rectangles and draw frames. The drawing types on this page determine how those operations appear.

const auto panel = Rectangle{2, 2, 30, 10};

buffer.fill(panel, Char{" ", Color{fg::Inherited, bg::Blue}});
buffer.drawFrame(panel, FrameStyle::LightWithRoundedCorners, Color{fg::BrightWhite, bg::Blue});
buffer.drawText("Overview", panel.insetBy(Margins{1}), Alignment::TopLeft);

FrameStyle is the fastest way to choose one of the built-in Unicode box styles. It works well for common UI elements such as panels, dialogs, and separators.

You can restyle the same layout code simply by changing the enum value:

buffer.drawFilledFrame(
    Rectangle{2, 4, 20, 4},
    FrameStyle::Light,
    Char{" ", Color{fg::Inherited, bg::Blue}},
    Color{fg::BrightCyan, bg::Inherited});
buffer.drawFilledFrame(
    Rectangle{25, 4, 20, 4},
    FrameStyle::LightWithRoundedCorners,
    Char{" ", Color{fg::Inherited, bg::Green}},
    Color{fg::BrightGreen, bg::Inherited});
buffer.drawFilledFrame(
    Rectangle{48, 9, 20, 4},
    FrameStyle::FullBlock,
    Char{" ", Color{fg::Inherited, bg::BrightBlack}});
                     Built-in FrameStyle presets                      
      Choose a built-in style without changing your layout code.      
                                                                      
         Light                 Rounded                 Heavy          
  ┌──────────────────┐   ╭──────────────────╮   ┏━━━━━━━━━━━━━━━━━━┓  
        panel                panel                panel         
                                                                
  └──────────────────┘   ╰──────────────────╯   ┗━━━━━━━━━━━━━━━━━━┛  
         Double               OuterHalf              FullBlock        
  ╔══════════════════╗   ▛▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▜   ████████████████████  
        panel                panel             panel       
                                                           
  ╚══════════════════╝   ▙▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▟   ████████████████████  
                                                                      

Combining Frames Automatically

When multiple frames intersect, drawing them directly on top of each other would produce broken or overlapping characters.

CharCombinationStyle resolves these overlaps by choosing the correct combined glyph for each intersection.

auto frameStyle = Char16Style::lightFrame();
auto combination = CharCombinationStyle::commonBoxFrame();

buffer.drawFrame(Rectangle{2, 2, 18, 8}, frameStyle, combination, Color{fg::BrightCyan, bg::Black});
buffer.drawFrame(Rectangle{8, 5, 20, 8}, frameStyle, combination, Color{fg::BrightYellow, bg::Black});

This ensures that intersecting lines produce consistent box-drawing characters instead of visual artifacts.

Drawing Grid Layouts

Use GridLayout when you want a stable table-like layout where content cells keep their own rectangles and the frame lines are drawn around them.

The FrameBorder object describes which outer and inner line groups are visible. A None element consumes no terminal cells, while supported line styles consume one cell and are resolved with their neighbors automatically. Block frame styles are not grid line styles and are treated like None here.

auto border = FrameBorder{FrameStyle::Light, Color{fg::BrightWhite, bg::Black}};
border.set(FrameBorderElement::HLine, FrameStyle::Heavy, Color{fg::BrightWhite, bg::Black});

auto layout = GridLayout{{16, 16, 16}, {3, 3}};
auto origin = Position{2, 2};

for (std::size_t row = 0; row < layout.rowCount(); ++row) {
    for (std::size_t column = 0; column < layout.columnCount(); ++column) {
        buffer.drawText(
            "cell",
            layout.cellRect(row, column, origin, border),
            Alignment::Center,
            Color{fg::BrightCyan, bg::Black});
    }
}
buffer.drawGridLayout(origin, layout, border);

This keeps content placement independent from the selected border style. If you later hide separator lines or switch from light to double borders, the same cellRect() calls still describe the usable content area.

The difference is easiest to see when the same pair of frames is rendered once with plain overwrite behavior and once with a box-aware combiner:

auto style = Char16Style::lightFrame();

buffer.drawFrame(
    Rectangle{2, 2, 17, 6},
    style,
    CharCombinationStyle::overwrite(),
    Color{fg::BrightCyan, bg::Inherited});
buffer.drawFrame(
    Rectangle{8, 4, 18, 6},
    style,
    CharCombinationStyle::overwrite(),
    Color{fg::BrightYellow, bg::Inherited});

buffer.drawFrame(
    Rectangle{37, 2, 17, 6},
    style,
    CharCombinationStyle::commonBoxFrame(),
    Color{fg::BrightCyan, bg::Inherited});
buffer.drawFrame(
    Rectangle{43, 4, 18, 6},
    style,
    CharCombinationStyle::commonBoxFrame(),
    Color{fg::BrightYellow, bg::Inherited});
            overwrite()                     commonBoxFrame()          
Later frames simply replace earlier   Intersections become matching   
  ┌───────────────┐                  ┌───────────────┐                
                                                                  
       ┌────────────────┐                ┌─────────┼──────┐         
                                                              
                                                              
  └──────────────┘                 └──────────────┘               
                                                                  
        └────────────────┘                 └────────────────┘         
                                                                      

To define your own combination behavior, use SimpleCharCombinationStyle for straightforward mappings or MatrixCombinationStyle for full control over all combinations.

Repeating 9-Tile Styles

Tile9Style fills or frames a rectangle using a repeating 3×3 tile layout.

This lets you define separate characters for corners, edges, and the center while still scaling cleanly to any size.

const auto panel = Rectangle{2, 2, 30, 10};
const auto style = Tile9Style::create("╔═╗║ ║╚═╝");

buffer.fill(panel, style, Color{fg::BrightBlack, bg::Black});
buffer.drawFrame(panel, style, Color{fg::BrightCyan, bg::Black});

The 9-tile layout covers the standard case: corners, edges, and center. You can also read a configured tile directly by name, for example style->block(Tile9Style::Element::West) or style->block(Tile9Style::Element::Center). This is useful for small theme-controlled text fragments that reuse the same tile table without drawing a rectangle.

If you also need specialized tiles for degenerate cases such as a single row, a single column, or a single cell, construct the style with 16 characters instead.

The left example below uses a decorative 9-tile pattern. The right side uses letter-coded 16-tile input so the special degenerate tiles are easy to identify:

const auto decorative = Tile9Style::create("╔═╗║·║╚═╝");
buffer.fill(Rectangle{3, 2, 28, 7}, decorative, Color{fg::BrightCyan, bg::Inherited});

const auto degenerate = Tile9Style::create("ABCDEFGHIJKLMNOP");
buffer.fill(Rectangle{39, 2, 10, 5}, degenerate, Color{fg::BrightYellow, bg::Inherited});
buffer.fill(Rectangle{52, 2, 10, 1}, degenerate, Color{fg::BrightYellow, bg::Inherited});
buffer.fill(Rectangle{52, 4, 1, 5}, degenerate, Color{fg::BrightYellow, bg::Inherited});
buffer.fill(Rectangle{57, 4, 1, 1}, degenerate, Color{fg::BrightYellow, bg::Inherited});
  9 tiles repeat edges and center    16 tiles cover thin edge cases   
                                                       row            
   ╔══════════════════════════╗        ABBBBBBBBC   JKKKKKKKKL        
   ║··························║        DEEEEEEEEF                     
   ║··········Repeat··········║        DEEEEEEEEF   M    P cell       
   ║··························║        DEEEEEEEEF   N                 
   ║··························║        GHHHHHHHHI   N                 
   ║··························║                     N                 
   ╚══════════════════════════╝          normal     O                 
                                                  column              
                                                                      
                                                                      

Configuring Reusable Frame Presets

When a frame configuration goes beyond a simple style and color, FrameDrawOptions lets you bundle all settings into a reusable object.

auto panelStyle = FrameDrawOptions{};
panelStyle.setStyle(FrameStyle::LightWithRoundedCorners);
panelStyle.setFillBlock(Char{" ", Color{fg::Inherited, bg::Black}});
panelStyle.setFrameColorSequence(
    ColorSequence{
        Color{fg::BrightBlue, bg::Black},
        Color{fg::BrightCyan, bg::Black},
        Color{fg::BrightWhite, bg::Black},
    },
    FrameColorMode::ChasingBorderCW);
panelStyle.setFillColor(Color{fg::Inherited, bg::Blue});

buffer.drawFrame(Rectangle{2, 2, 28, 10}, panelStyle, animationCycle);
buffer.drawFrame(Rectangle{34, 2, 28, 10}, panelStyle, animationCycle + 4);

This approach is especially useful when the same panel style is reused throughout your application, or when you work with animated borders, custom fill behavior, or non-default combination rules.

Because FrameDrawOptions bundles style, fill, and color animation in one object, it is also a good fit for reusable presets:

auto stripeOptions = FrameDrawOptions{};
stripeOptions.setStyle(FrameStyle::Double);
stripeOptions.setFillBlock(Char{" "});
stripeOptions.setFrameColorSequence(
    ColorSequence{
        Color{fg::BrightYellow, bg::Inherited},
        Color{fg::BrightMagenta, bg::Inherited},
        Color{fg::BrightCyan, bg::Inherited},
    },
    FrameColorMode::VerticalStripes);
stripeOptions.setFillColorSequence(
    ColorSequence{
        Color{fg::Inherited, bg::Blue},
        Color{fg::Inherited, bg::Magenta},
    },
    FrameColorMode::HorizontalStripes);

auto chasingOptions = FrameDrawOptions{};
chasingOptions.setStyle(FrameStyle::Heavy);
chasingOptions.setFillBlock(Char{"·", Color{fg::BrightBlack, bg::Inherited}});
chasingOptions.setFrameColorSequence(
    ColorSequence{
        Color{fg::BrightRed, bg::Inherited},
        Color{fg::BrightYellow, bg::Inherited},
        Color{fg::BrightGreen, bg::Inherited},
        Color{fg::BrightCyan, bg::Inherited},
    },
    FrameColorMode::ChasingBorderCW);

buffer.drawFrame(Rectangle{24, 1, 22, 8}, stripeOptions);
buffer.drawFrame(Rectangle{47, 1, 22, 8}, chasingOptions, 3);
      Static fill         Striped sequences        Chasing border     
 ╭────────────────────╮   
                                           ···················· 
                                           ···················· 
                                           ···················· 
                                           ···················· 
                                           ···················· 
                                           ···················· 
 ╰────────────────────╯   
      fixed colors           stripe modes            cycle = 3        
                                                                      

Choosing the Right Style

Each drawing style has a slightly different purpose:

  • Use FrameStyle when a predefined border style is enough.

  • Use Char16Style when each cell should adapt to its neighbors, for example for custom line art or circuit-like rendering.

  • Use Tile9Style when corners, edges, and center tiles should scale independently.

Choosing the right abstraction early keeps your rendering code simpler and avoids unnecessary post-processing later.

Interface

class Char16Style

Defines a style for drawing tiles.

Public Functions

inline explicit Char16Style(std::array<Char, 16> tiles) noexcept

Create a new tile 16 style.

Connection points/bits: E:0, S:1, W:2, N:3

explicit Char16Style(std::string_view tiles)

Create a new tile 16 style from 16 terminal characters.

Connection points/bits: E:0, S:1, W:2, N:3

Parameters:

tiles – A sequence of exactly 16 terminal characters.

Throws:

std::invalid_argument – If tiles does not contain exactly 16 terminal characters.

explicit Char16Style(std::u32string_view tiles)

Create a new tile 16 style from 16 terminal characters.

Connection points/bits: E:0, S:1, W:2, N:3

Parameters:

tiles – A sequence of exactly 16 terminal characters.

Throws:

std::invalid_argument – If tiles does not contain exactly 16 terminal characters.

Char block(uint32_t bitMask) const noexcept

Access the block for a given bit combination.

Parameters:

bitMask – The bit-mask E:0, S:1, W:2, N:3.

Returns:

The block for the given bit combination, or an empty block if the bits are out of bounds.

Public Static Functions

static Char16StylePtr create(std::string_view tiles)

Create a new shared style from 16 terminal characters.

Parameters:

tiles – A sequence of exactly 16 terminal characters.

Throws:

std::invalid_argument – If tiles does not contain exactly 16 terminal characters.

Returns:

A shared style instance.

static Char16StylePtr create(std::u32string_view tiles)

Create a new shared style from 16 terminal characters.

Parameters:

tiles – A sequence of exactly 16 terminal characters.

Throws:

std::invalid_argument – If tiles does not contain exactly 16 terminal characters.

Returns:

A shared style instance.

static Char16StylePtr lightFrame()

For drawing light frames.

static Char16StylePtr lightDoubleDashFrame()

For drawing light frames with double-dashed lines.

static Char16StylePtr lightTripleDashFrame()

For drawing light frames with triple-dashed lines.

static Char16StylePtr lightQuadrupleDashFrame()

For drawing light frames with quadruple-dashed lines.

static Char16StylePtr lightRoundedFrame()

For drawing light frames with rounded corners.

static Char16StylePtr heavyFrame()

For drawing heavy frames.

static Char16StylePtr heavyDoubleDashFrame()

For drawing heavy frames with double-dashed lines.

static Char16StylePtr heavyTripleDashFrame()

For drawing heavy frames with triple-dashed lines.

static Char16StylePtr heavyQuadrupleDashFrame()

For drawing heavy frames with quadruple-dashed lines.

static Char16StylePtr doubleFrame()

For drawing double frames.

static Char16StylePtr fullBlockFrame()

For drawing solid block frames.

static Char16StylePtr fullBlockWithChamferFrame()

For drawing solid block frames with chamfered corners.

static Char16StylePtr noneFrame()

For drawing empty frames with colored spaces.

static Char16StylePtr forStyle(FrameStyle frameStyle)

Get the style for the given frame style.

Parameters:

frameStyle – The frame style to resolve.

Returns:

The shared style instance, or nullptr if frameStyle requires Tile9Style.

using erbsland::cterm::Char16StylePtr = std::shared_ptr<Char16Style>

Shared pointer for Char16Style.

class CharCombinationStyle

A style how two characters are visually combined to a new one.

Subclassed by erbsland::cterm::CommonBoxFrameCombinationStyle, erbsland::cterm::MatrixCombinationStyle, erbsland::cterm::SimpleCharCombinationStyle

Public Functions

inline virtual bool isSurroundingAware() const noexcept

Does this style take the surrounding character into account? If this method returns false, combine with current as a single character is called.

If this method returns true, combine with current and overlay is called.

virtual Char combine(const Char &current, const Char &overlay) const noexcept

Combines the current char with a new that is placed on top of the current one.

The default implementation just returns the overlay character.

Parameters:
  • current – The current (lower) character.

  • overlay – The new (upper) character that overlays the current one.

Returns:

The combined character.

virtual Char combine(const std::array<const Char*, 9> &current, const Char &overlay) const noexcept

Combines the current character situation with a new overlay character that is placed on top of the current one.

The default implementation just returns the overlay character. The matrix starts at (-1, -1) and ends at (1, 1) (left to right, top to bottom).

Parameters:
  • current – A 3x3 matrix with nullptr for locations outside the buffer.

  • overlay – The new (upper) character that overlays the current one.

Returns:

The combined character.

Public Static Functions

static const CharCombinationStylePtr &overwrite() noexcept

Overwrite the character and color.

static const CharCombinationStylePtr &colorOverlay() noexcept

Overwrite the character but overlay the color.

static const CharCombinationStylePtr &commonBoxFrame() noexcept

Combine light, double, and heavy frames.

In that order: double overwrites light, and heavy overwrites double and light. Colors are overlay.

using erbsland::cterm::CharCombinationStylePtr = std::shared_ptr<CharCombinationStyle>

Shared pointer for CharCombinationStyle.

class SimpleCharCombinationStyle : public erbsland::cterm::CharCombinationStyle

A class to use a simple map to combine styles.

It uses a map of [current, overlay] -> combined and uses Color::overlayWith to combine the colors. If a character is missing in the map, the overlay overwrites the current one.

Public Types

using Map = std::map<std::string, std::string>

The map, where the key is <current>+<overlay>, and the value is the combined character.

Public Functions

SimpleCharCombinationStyle() = default

Create an empty combination style.

explicit SimpleCharCombinationStyle(Map map) noexcept

Create a new instance from the given map.

virtual Char combine(const Char &current, const Char &overlay) const noexcept override

Combines the current char with a new that is placed on top of the current one.

The default implementation just returns the overlay character.

Parameters:
  • current – The current (lower) character.

  • overlay – The new (upper) character that overlays the current one.

Returns:

The combined character.

const Map &map() const noexcept

Access the current map.

void setMap(Map map) noexcept

Replace the map.

void add(const std::string &current, const std::string &overlay, const std::string &combined) noexcept

Add a new entry to the map.

class MatrixCombinationStyle : public erbsland::cterm::CharCombinationStyle

A class that combines characters through an indexed result matrix.

It uses supported Unicode code points and a compact byte matrix of result indexes. Unknown characters fall back to the overlay character.

Public Functions

MatrixCombinationStyle(std::u32string characters, std::string_view resultMatrix)

Create a new matrix-based combination style.

Parameters:
  • characters – The supported Unicode characters in matrix index order.

  • resultMatrix – The result matrix in row-major order using result indexes. The matrix size must be characters.size() * characters.size().

Throws:

std::invalid_argument – If the matrix size is invalid or the character count exceeds 255.

virtual Char combine(const Char &current, const Char &overlay) const noexcept override

Combines the current char with a new that is placed on top of the current one.

The default implementation just returns the overlay character.

Parameters:
  • current – The current (lower) character.

  • overlay – The new (upper) character that overlays the current one.

Returns:

The combined character.

class Tile9Style

Defines a style for repeating a 3x3 tile pattern across a rectangle.

The 9-tile layout uses this arrangement: top-left, top, top-right, left, center, right, bottom-left, bottom, bottom-right.

Optionally, 7 additional tiles can be provided for degenerate rectangles: single-row left, single-row center, single-row right, single-column top, single-column center, single-column bottom, and the single-cell tile.

Public Types

enum class Element : uint8_t

Named elements of the 16-tile style table.

Values:

enumerator NorthWest

Top-left tile.

enumerator North

Top edge tile.

enumerator NorthEast

Top-right tile.

enumerator West

Left edge tile.

enumerator Center

Center tile.

enumerator East

Right edge tile.

enumerator SouthWest

Bottom-left tile.

enumerator South

Bottom edge tile.

enumerator SouthEast

Bottom-right tile.

enumerator HorizontalWest

Left tile for one-row rectangles.

enumerator HorizontalCenter

Center tile for one-row rectangles.

enumerator HorizontalEast

Right tile for one-row rectangles.

enumerator VerticalNorth

Top tile for one-column rectangles.

enumerator VerticalCenter

Center tile for one-column rectangles.

enumerator VerticalSouth

Bottom tile for one-column rectangles.

enumerator Single

Single-cell tile.

Public Functions

explicit Tile9Style(std::array<Char, 9> tiles) noexcept

Create a new 9-tile style from the repeating 3x3 tile layout.

Parameters:

tiles – The 3x3 tiles in row-major order.

explicit Tile9Style(std::array<Char, 16> tiles) noexcept

Create a new 9-tile style with explicit tiles for degenerate rectangles.

Parameters:

tiles – The 3x3 tiles followed by 7 degenerate tiles.

explicit Tile9Style(std::array<char32_t, 16> tiles, CharStyle style) noexcept

Create a new 9-tile style from code points and one shared style.

Parameters:
  • tiles – The 3x3 tiles followed by 7 degenerate tiles.

  • style – The shared style for all tiles.

explicit Tile9Style(std::string_view tiles)

Create a new 9-tile style from 9 or 16 terminal characters.

Parameters:

tiles – A sequence of 9 tiles, or 16 tiles including the degenerate cases.

Throws:

std::invalid_argument – If tiles does not contain exactly 9 or 16 terminal characters.

explicit Tile9Style(std::u32string_view tiles)

Create a new 9-tile style from 9 or 16 terminal characters.

Parameters:

tiles – A sequence of 9 tiles, or 16 tiles including the degenerate cases.

Throws:

std::invalid_argument – If tiles does not contain exactly 9 or 16 terminal characters.

Char block(Rectangle rect, Position pos) const noexcept

Resolve the tile for a given position inside a rectangle.

The center and edge tiles are repeated as needed.

Parameters:
  • rect – The styled rectangle.

  • pos – A position inside rect.

Returns:

The resolved tile, or an empty character if pos is outside rect.

Char block(Element element) const noexcept

Access one element of the 16-tile table by name.

Parameters:

element – The tile element to read.

Returns:

The configured tile. Extended-only elements fall back to their base-tile counterpart for 9-tile styles.

Public Static Functions

static Tile9StylePtr create(std::string_view tiles)

Create a new shared style from 9 or 16 terminal characters.

Parameters:

tiles – A sequence of 9 tiles, or 16 tiles including the degenerate cases.

Throws:

std::invalid_argument – If tiles does not contain exactly 9 or 16 terminal characters.

Returns:

A shared style instance.

static Tile9StylePtr create(std::u32string_view tiles)

Create a new shared style from 9 or 16 terminal characters.

Parameters:

tiles – A sequence of 9 tiles, or 16 tiles including the degenerate cases.

Throws:

std::invalid_argument – If tiles does not contain exactly 9 or 16 terminal characters.

Returns:

A shared style instance.

static Tile9StylePtr outerHalfBlockFrame()

For drawing half-block frames on the outer cell edges.

static Tile9StylePtr innerHalfBlockFrame()

For drawing half-block frames on the inner cell edges.

static Tile9StylePtr forStyle(FrameStyle frameStyle)

Get the tile-9 style for a predefined frame style.

Parameters:

frameStyle – The frame style to resolve.

Returns:

The matching tile-9 style, or nullptr if the frame style uses Char16Style.

using erbsland::cterm::Tile9StylePtr = std::shared_ptr<Tile9Style>

Shared pointer for Tile9Style.

enum class erbsland::cterm::FrameStyle : uint8_t

Various box styles.

Values:

enumerator None

No visible frame; regular frame drawing uses colored spaces.

enumerator Light

Light box ┌─┐

enumerator LightDoubleDash

Light box with double-dashed lines ┌╌┐

enumerator LightTripleDash

Light box with triple-dashed lines ┌┄┐

enumerator LightQuadrupleDash

Light box with quadruple-dashed lines ┌┈┐

enumerator Heavy

Heavy box ┏━┓

enumerator HeavyDoubleDash

Heavy box with double-dashed lines ┏╍┓

enumerator HeavyTripleDash

Heavy box with triple-dashed lines ┏┅┓

enumerator HeavyQuadrupleDash

Heavy box with quadruple-dashed lines ┏┉┓

enumerator Double

Double box ╔═╗

enumerator LightWithRoundedCorners

Light box with rounded corners ╭─╮

enumerator FullBlock

Solid block frame

enumerator FullBlockWithChamfer

Solid block frame with chamfered corners ◢█◣

enumerator OuterHalfBlock

Half-block frame drawn on the outer cell edges.

enumerator InnerHalfBlock

Half-block frame drawn on the inner cell edges.

enum class erbsland::cterm::FrameBorderElement : uint8_t

Named line groups for a grid frame border.

Values:

enumerator Top

The top outer line.

enumerator Bottom

The bottom outer line.

enumerator Left

The left outer line.

enumerator Right

The right outer line.

enumerator HLine

The horizontal separator lines between rows.

enumerator VLine

The vertical separator lines between columns.

class FrameBorder

Styling for all line groups of a grid frame.

The default border draws no lines. Use the all-style constructor or set() to enable individual line groups.

Tested:

FrameBorderTest

Public Types

using Element = FrameBorderElement

The named line groups for this border.

Public Functions

FrameBorder() = default

Create a border with all elements set to FrameStyle::None.

explicit FrameBorder(FrameStyle style, Color color = {}) noexcept

Create a border with the same style and color for all elements.

Parameters:
  • style – The style to apply to all elements.

  • color – The color to apply to all elements.

const Border &border(Element element) const noexcept

Access the style and color for an element.

Parameters:

element – The element to query.

Returns:

The configured style and color.

FrameStyle style(Element element) const noexcept

Access the frame style for an element.

Parameters:

element – The element to query.

Returns:

The configured frame style.

Color color(Element element) const noexcept

Access the color for an element.

Parameters:

element – The element to query.

Returns:

The configured color.

void set(Element element, FrameStyle style, Color color = {}) noexcept

Set the style and color for an element.

Parameters:
  • element – The element to change.

  • style – The new frame style.

  • color – The new color.

Char corner(Anchor anchor) const noexcept

Resolve one of the nine grid corner or joint characters for this border.

Parameters:

anchor – One of the nine composite anchor values.

Returns:

The resolved joint character.

Public Static Functions

static bool isLineStyle(FrameStyle style) noexcept

Test if a frame style can be used as a one-cell grid line style.

Parameters:

style – The style to test.

Returns:

true for None and supported line frame styles.

static Char cornerChar(Border east, Border south, Border west, Border north) noexcept

Resolve the character for a grid corner or joint from its four directed borders.

Color precedence is east, west, south, north; inherited color parts fall through to lower-priority borders.

Parameters:
  • east – The border segment going to the right.

  • south – The border segment going down.

  • west – The border segment going to the left.

  • north – The border segment going up.

Returns:

The resolved joint character.

struct Border

Style and color for one border element.

Public Members

FrameStyle style = {FrameStyle::None}

The frame style for this element.

Color color = {}

The color for this element.

class GridLayout

Geometry for a grid of content cells.

This class stores only content sizes.

Tested:

GridLayoutTest

Public Functions

GridLayout(std::vector<Coordinate> columnWidths, std::vector<Coordinate> rowHeights)

Create a grid layout.

Parameters:
  • columnWidths – The content width of each column. Each value must be positive.

  • rowHeights – The content height of each row. Each value must be positive.

Throws:

std::invalid_argument – if either list is empty or contains a non-positive size.

GridLayout(std::initializer_list<Coordinate> columnWidths, std::initializer_list<Coordinate> rowHeights)

Create a grid layout from initializer lists.

Parameters:
  • columnWidths – The content width of each column. Each value must be positive.

  • rowHeights – The content height of each row. Each value must be positive.

Throws:

std::invalid_argument – if either list is empty or contains a non-positive size.

std::size_t rowCount() const noexcept

Number of rows in the grid.

std::size_t columnCount() const noexcept

Number of columns in the grid.

Coordinate rowHeight(std::size_t row) const

Access one row height.

Parameters:

row – The row index.

Throws:

std::out_of_range – if row is outside the layout.

Returns:

The row content height.

Coordinate columnWidth(std::size_t column) const

Access one column width.

Parameters:

column – The column index.

Throws:

std::out_of_range – if column is outside the layout.

Returns:

The column content width.

const std::vector<Coordinate> &rowHeights() const noexcept

Access all row heights.

const std::vector<Coordinate> &columnWidths() const noexcept

Access all column widths.

Size size(const FrameBorder &border) const noexcept

Calculate the complete size of this layout for the given border.

Parameters:

border – Border styles that decide which frame lines occupy cells.

Returns:

The total grid size including active frame lines.

Rectangle cellRect(std::size_t row, std::size_t column, Position origin, const FrameBorder &border) const

Calculate the content rectangle for one cell.

Parameters:
  • row – The row index.

  • column – The column index.

  • origin – The top-left position of the full grid.

  • border – Border styles that decide which frame lines occupy cells.

Throws:

std::out_of_range – if row or column is outside the layout.

Returns:

The cell content rectangle.

enum class erbsland::cterm::FrameColorMode : uint8_t

The mode how animated colors are applied to frames.

Values:

enumerator OneColor

Uses one color from the sequence for the whole frame or fill area.

The selected sequence entry is animationCycle + animationOffset.

enumerator VerticalStripes

Uses the color sequence in vertical stripes.

The selected sequence entry is x + animationCycle + animationOffset.

enumerator HorizontalStripes

Uses the color sequence in horizontal stripes.

The selected sequence entry is y + animationCycle + animationOffset.

enumerator ForwardDiagonalStripes

Uses the color sequence in forward diagonal stripes.

The selected sequence entry is x + y + animationCycle + animationOffset.

enumerator BackwardDiagonalStripes

Uses the color sequence in backward diagonal stripes.

The selected sequence entry is -x + y + animationCycle + animationOffset.

enumerator ChasingBorderCW

Uses the color sequence along the frame border in clockwise order.

Increasing animationCycle makes the colors travel clockwise.

enumerator ChasingBorderCCW

Uses the color sequence along the frame border in clockwise order.

Increasing animationCycle makes the colors travel counter-clockwise.

class FrameDrawOptions

The options to draw a frame.

These options define the frame style, optional fill, combination style, and animated color behavior for Buffer::drawFrame(). The style priority is tile9Style(), then char16Style(), and finally style(). If a Tile9Style is active, it also controls the fill area and overrides fillBlock(). Frame colors are overlaid as buffer -> frameColor -> tile/block color. Fill colors are overlaid as buffer -> frameColor -> fillColor -> tile/block color.

Note

Creating custom option instances is expensive. Reuse them across multiple drawFrame() calls.

Public Functions

FrameDrawOptions() = default

Create default frame draw options.

template<typename tColor>
inline explicit FrameDrawOptions(tColor frameColor)

Create options for one fixed frame color.

Parameters:

frameColor – The base frame color.

explicit FrameDrawOptions(ColorSequence frameColor, FrameColorMode frameColorMode = FrameColorMode::OneColor)

Create options from a frame color sequence.

Parameters:
  • frameColor – The base frame colors.

  • frameColorMode – The mode used to pick colors from the frame sequence.

const ColorSequence &frameColor() const noexcept

The frame color sequence.

If this contains only inherited colors, the frame inherits the full color from the buffer below.

void setFrameColor(Color frameColor) noexcept

Set a single frame color.

void setFrameColor(Foreground foreground, Background background) noexcept

Set explicit foreground and background colors for the frame.

void setFrameColorSequence(ColorSequence frameColor, FrameColorMode frameColorMode = FrameColorMode::OneColor) noexcept

Set the frame color sequence.

const ColorSequence &fillColor() const noexcept

The fill color sequence.

The fill colors are applied after frameColor(), which allows subtle adjustments on top of animated borders.

void setFillColor(Color fillColor) noexcept

Set a single fill color.

void setFillColor(Foreground foreground, Background background) noexcept

Set explicit foreground and background colors for the fill.

void setFillColorSequence(ColorSequence fillColor, FrameColorMode fillColorMode = FrameColorMode::OneColor) noexcept

Set the fill color sequence.

const Char &fillBlock() const noexcept

The fill block.

An empty block disables filling when no Tile9Style is active.

void setFillBlock(Char fillBlock) noexcept

Set the fill block.

Use Char{} to disable the fill.

FrameStyle style() const noexcept

The predefined frame style.

void setStyle(FrameStyle style) noexcept

Set the predefined frame style.

const Char16StylePtr &char16Style() const noexcept

The custom Char16 frame style.

This overrides style() unless tile9Style() is also set.

void setChar16Style(Char16StylePtr char16Style) noexcept

Set the custom Char16 frame style.

const Tile9StylePtr &tile9Style() const noexcept

The custom Tile9 frame style.

This overrides both char16Style() and style(), and also controls the fill area.

void setTile9Style(Tile9StylePtr tile9Style) noexcept

Set the custom Tile9 frame style.

const CharCombinationStylePtr &combinationStyle() const noexcept

The combination style used for writing the frame and fill blocks.

void setCombinationStyle(CharCombinationStylePtr combinationStyle) noexcept

Set the combination style.

std::size_t animationOffset() const noexcept

The shared animation offset for frame and fill colors.

This value is added to the animationCycle passed to drawFrame().

void setAnimationOffset(std::size_t offset) noexcept

Set the animation offset for frame and fill colors.

FrameColorMode frameColorMode() const noexcept

The frame color mode.

void setFrameColorMode(FrameColorMode frameColorMode) noexcept

Set the frame color mode.

FrameColorMode fillColorMode() const noexcept

The fill color mode.

ChasingBorderCW and ChasingBorderCCW only affect frame cells.

void setFillColorMode(FrameColorMode fillColorMode) noexcept

Set the fill color mode.

Public Static Functions

static const FrameDrawOptions &defaultOptions() noexcept

Access the shared object with the default options.

Default options use a light Unicode frame, inherited colors, no fill, and the common box frame combiner.