pub struct Frame { /* private fields */ }Expand description
Logical output from a Component::render call: a vector of Lines plus a Cursor position.
A Frame is the only render artifact of a component. Composition between parents and children happens by transforming and stacking frames — not by reaching back into raw Vec<Line>. Raw line vectors remain a useful internal convenience inside a single component, but they are not the public composition primitive.
The Renderer consumes frames, diffs them against the previous render, and emits only the changed ANSI sequences.
§Construction
use tui::{Frame, Line};
use tui::Cursor;
let frame = Frame::new(vec![
Line::new("Hello, world!"),
Line::new("Press q to quit"),
]);
// Optionally place a visible cursor
let frame = frame.with_cursor(Cursor::visible(0, 5));§Composition
All composition operations live on Frame itself and own the cursor remapping for the transform they perform.
fit(width, options)— Wrap or truncate each row to a target width, optionally extending each row to that width with the row’s background color. SeeFitOptionsandOverflow.indent(cols)— Shift visual contentcolscolumns to the right and shift the cursor.vstack(frames)— Concatenate frames vertically. The first visible cursor wins; its row is offset by the cumulative line count of preceding frames.hstack(parts)— ComposeFramePartslots horizontally into fixed-width columns. Heights are balanced by padding shorter slots with blank rows of the slot’s width. The first visible cursor wins; its column is offset by the cumulative width of preceding slots.
These primitives are intentionally small. Containers should compose with them rather than reimplementing wrap, pad, or cursor math by hand.
§Other methods
lines()— Borrow the rendered lines.cursor()— The current cursor state.with_cursor(cursor)— Replace the cursor (builder pattern, movesself).clamp_cursor()— Clamp the cursor row to the last line index, preventing out-of-bounds positions.into_lines()— Consume the frame and return the lines.into_parts()— Consume and return(Vec<Line>, Cursor).empty()— Construct an empty frame with a hidden cursor.
§See also
Cursor— Logical cursor with row, col, and visibility.Line— A single line of styled terminal output.ViewContext— The allocated render region passed intoComponent::render.Renderer— Consumes frames and renders them to the terminal.Frame::vstack— Composes multiple frames vertically.
Implementations§
Source§impl Frame
impl Frame
pub fn new(lines: Vec<Line>) -> Self
pub fn lines(&self) -> &[Line]
pub fn cursor(&self) -> Cursor
Sourcepub fn with_cursor(self, cursor: Cursor) -> Self
pub fn with_cursor(self, cursor: Cursor) -> Self
Replace the cursor without cloning lines.
pub fn into_lines(self) -> Vec<Line>
pub fn into_parts(self) -> (Vec<Line>, Cursor)
pub fn clamp_cursor(self) -> Self
Sourcepub fn fit(self, width: u16, options: FitOptions) -> Self
pub fn fit(self, width: u16, options: FitOptions) -> Self
Fit the frame to a target width.
Overflow::Wrap: each line is soft-wrapped towidth. The cursor row is remapped to the wrapped visual row, and the cursor column is reduced modulowidth, with the row advanced for any overflow. This matches the wrap math used byVisualFrame.Overflow::Truncate: each line is truncated towidth. Row count is unchanged. The cursor column is clamped towidth.saturating_sub(1).fill_x: every resulting row is marked with row-fill metadata using any background color present on the row. The fill is not materialized into trailing spaces here — that happens later, inFrame::hstack(per slot width) orVisualFrame(per terminal width). Deferring materialization is what prevents trailing-space rows from producing phantom rows when wrapped again at a smaller width.
As a special case, width == 0 returns the frame unchanged with a
hidden cursor (matching the zero-width behavior of VisualFrame).
Sourcepub fn indent(self, cols: u16) -> Self
pub fn indent(self, cols: u16) -> Self
Shift visual content cols columns to the right by prepending spaces
to each line. The cursor column is shifted by cols. The row is
unchanged.
The prepended prefix inherits any background color from the line, so row-fill highlights extend through the indent.
Sourcepub fn vstack(frames: impl IntoIterator<Item = Frame>) -> Self
pub fn vstack(frames: impl IntoIterator<Item = Frame>) -> Self
Concatenate frames vertically.
The first frame in the iterator that has a visible cursor wins. Its row is offset by the cumulative line count of all preceding frames.
Sourcepub fn hstack(parts: impl IntoIterator<Item = FramePart>) -> Self
pub fn hstack(parts: impl IntoIterator<Item = FramePart>) -> Self
Compose frames horizontally into fixed-width slots.
Each part’s frame is assumed to already fit its width (callers should
fit(width, FitOptions::wrap()) or similar first). Any row-fill
metadata on a part’s rows is materialized to the part’s slot width
before merging, so trailing fill never bleeds into a neighboring slot.
Heights are balanced by padding shorter frames with blank rows of the
slot’s width. The first part with a visible cursor wins; its column is
offset by the cumulative width of preceding slots.
Sourcepub fn map_lines<T: FnMut(Line) -> Line>(self, f: T) -> Self
pub fn map_lines<T: FnMut(Line) -> Line>(self, f: T) -> Self
Apply f to each line in turn, preserving cursor and overall row
count. The function may not split or merge rows; doing so will leave
the cursor pointing at the wrong row.
Sourcepub fn prefix(self, head: &Line, tail: &Line) -> Self
pub fn prefix(self, head: &Line, tail: &Line) -> Self
Prepend a fixed-width gutter to each row. The first row gets head,
subsequent rows get tail. Use the same value for both for a uniform
gutter, or different values for first/continuation patterns (e.g.,
line numbers on the first row of a wrapped block, blanks on the rest).
head and tail must have equal display width — debug-asserted. The
cursor column is shifted by that width. Any row-fill metadata on the
original row is preserved on the prefixed row.
Sourcepub fn pad_height(self, target: u16, width: u16) -> Self
pub fn pad_height(self, target: u16, width: u16) -> Self
Pad with blank rows of width columns until at least target rows
total. No-op if already at or above target. Cursor preserved.
Sourcepub fn truncate_height(self, target: u16) -> Self
pub fn truncate_height(self, target: u16) -> Self
Truncate to at most target rows. If the visible cursor falls beyond
the truncation, it is hidden.
Sourcepub fn fit_height(self, target: u16, width: u16) -> Self
pub fn fit_height(self, target: u16, width: u16) -> Self
Force the frame to exactly target rows: truncate if taller, pad with
blank rows of width columns if shorter. Convenience for layouts that
emit a fixed-height region regardless of child content.
Sourcepub fn wrap_each(self, inner_width: u16, left: &Line, right: &Line) -> Self
pub fn wrap_each(self, inner_width: u16, left: &Line, right: &Line) -> Self
Wrap each row in side chrome: materialize fill to inner_width, then
prepend left and append right to every row. The cursor column is
shifted by left.display_width().
Used for borders/box chrome where the row’s interior should fill its allocated width before the right edge is appended.
Sourcepub fn splice(self, after_row: usize, other: Frame) -> Self
pub fn splice(self, after_row: usize, other: Frame) -> Self
Insert the lines of other into this frame immediately after after_row.
Rows 0..=after_row remain in place. The lines of other appear
between row after_row and what was previously row after_row + 1.
Rows that followed the insertion point shift down by
other.lines().len().
If after_row >= self.lines.len(), the lines are appended at the end.
Cursor rule (consistent with vstack / hstack): the host frame’s
visible cursor takes priority — shifted down when it sits after the
insertion point. Otherwise, other’s visible cursor is adopted with
its row offset to the insertion position.
Trait Implementations§
impl Eq for Frame
impl StructuralPartialEq for Frame
Auto Trait Implementations§
impl Freeze for Frame
impl RefUnwindSafe for Frame
impl Send for Frame
impl Sync for Frame
impl Unpin for Frame
impl UnsafeUnpin for Frame
impl UnwindSafe for Frame
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more