Buffer Views

Buffer views expose a rectangular window onto a larger readable buffer.

They are the right tool whenever your logical content is larger than the visible terminal area—for example in scrollable panels, editors, minimaps, or diagnostic tools.

BufferViewBase provides the shared view behavior, BufferView owns a shared pointer to the underlying content, and BufferConstRefView is the lightweight, stack-friendly variant for temporary rendering.

Usage

Viewing a Portion of a Larger Buffer

Use a buffer view when you want to render only a specific region of a larger logical canvas.

auto world = Buffer{Size{120, 40}};
world.fill(Block{" ", Color{fg::Inherited, bg::Black}});
world.drawBlockText("Visible window", Rectangle{10, 6, 20, 3}, Alignment::Center);

auto view = BufferConstRefView{world, Rectangle{8, 4, 40, 12}};

auto settings = UpdateSettings{};
settings.setShowCropMarks(true);
terminal.updateScreen(view, settings);

The view translates its local coordinates into the corresponding positions of the underlying buffer. This allows you to render just the visible portion without copying or modifying the original content.

Scrolling by Moving the View Rectangle

BufferViewBase stores the currently visible rectangle, which you can update as the user scrolls or pans through the content.

auto sharedWorld = std::make_shared<Buffer>(world);
auto view = BufferView{sharedWorld, Rectangle{0, 0, 40, 12}};

view.setViewRect(Rectangle{16, 10, 40, 12});
terminal.updateScreen(view);

By moving the view rectangle, you change which part of the content is visible—without copying, reallocating, or redrawing the underlying buffer.

Choosing Between Shared and Referenced Views

Choose BufferView when the view needs to outlive the current scope or be stored as part of a larger object.

Choose BufferConstRefView when you only need a short-lived wrapper around an existing buffer.

auto sharedBuffer = std::make_shared<Buffer>(Size{80, 24});
auto cachedView = BufferView{sharedBuffer, Rectangle{4, 4, 30, 10}};

auto preview = BufferConstRefView{*sharedBuffer, Rectangle{0, 0, 20, 6}};
terminal.updateScreen(preview);

Both variants implement ReadableBuffer, so the rest of your rendering pipeline can treat them just like any other source of terminal cells.

Showing Cropped Edges Explicitly

CropEdges describes which sides of a view are clipped by the available content.

BufferViewBase can use this information to render custom crop indicators directly inside the view.

auto sharedBuffer = std::make_shared<Buffer>(world);
auto view = BufferView{sharedBuffer, Rectangle{8, 4, 40, 12}};

view.setShowCropCharacters(true);
view.setCropCharacter(Direction::East, Block{U'▶', fg::BrightYellow});
view.setCropCharacter(Direction::South, Block{U'▼', fg::BrightYellow});

const auto cropEdges = CropEdges::fromView(view.viewRect(), sharedBuffer->rect());
if (cropEdges.isSet(Direction::East)) {
    terminal.printLine("There is more content to the right.");
}

This is especially helpful in scrollable views, where users should immediately recognize that additional content exists beyond the visible window.

If you are already using the UI framework, see ui::ScrollingBufferView for the same concept packaged as a ready-to-use surface with scroll and page navigation helpers.