Skip to main content

TextBlock

Struct TextBlock 

Source
pub struct TextBlock { /* private fields */ }
Expand description

A multi-line text widget with wrapping support.

TextBlock is intentionally a pure renderer:

  • It does not own scroll state.
  • Scrolling/clipping should be implemented by drawing into a WindowView with scroll offsets (or by using ScrollBox / Viewport + ScrollState).

Implementations§

Source§

impl TextBlock

Source

pub fn new(width: u16, height: u16, text: impl Into<String>) -> Self

Creates a new TextBlock with the given size and content.

Examples found in repository?
examples/widget_usage.rs (lines 113-120)
41fn create_app_layout(term_w: u16, term_h: u16) -> Container {
42    // `ContainerPadding` is what the prelude exports (the underlying type is `Padding`).
43    use minui::widgets::ContainerPadding;
44
45    // A simple "fill the terminal" root. Children will be laid out inside it.
46    // We make it vertical with a row gap so sections are visually separated.
47    let root = Container::new()
48        .with_position_and_size(0, 0, term_w, term_h)
49        .with_layout_direction(LayoutDirection::Vertical)
50        .with_row_gap(Gap::Pixels(1))
51        .with_padding(ContainerPadding::uniform(1));
52
53    // Header: fixed height so it behaves like an app bar.
54    let header_h: u16 = 3;
55    let header = Container::new()
56        .with_position_and_size(0, 0, term_w.saturating_sub(2), header_h)
57        .with_layout_direction(LayoutDirection::Vertical)
58        .with_border()
59        .with_border_chars(BorderChars::double_line())
60        .with_border_color(ColorPair::new(Color::LightBlue, Color::Black))
61        .with_title("MinUI Widget Demo")
62        .with_title_alignment(TitleAlignment::Center)
63        .with_padding(ContainerPadding::symmetric(0, 1))
64        .add_child(Label::new("Press 'q' to quit").with_text_color(Color::Cyan));
65
66    // Footer: also fixed height.
67    let footer_h: u16 = 3;
68    let footer = Container::new()
69        .with_position_and_size(0, 0, term_w.saturating_sub(2), footer_h)
70        .with_layout_direction(LayoutDirection::Vertical)
71        .with_border()
72        .with_border_chars(BorderChars::single_line())
73        .with_border_color(ColorPair::new(Color::Yellow, Color::Black))
74        .with_padding(ContainerPadding::symmetric(0, 1))
75        .add_child(Label::new("Status: Ready • Press 'q' to quit").with_text_color(Color::Yellow));
76
77    // Body: fills the remaining space (best-effort). We size it explicitly so content has a
78    // stable viewport, but rely on Container layout for its children.
79    let body_h = term_h
80        .saturating_sub(1) // root padding top
81        .saturating_sub(1) // root padding bottom
82        .saturating_sub(header_h)
83        .saturating_sub(1) // root row gap between header/body
84        .saturating_sub(footer_h)
85        .saturating_sub(1); // root row gap between body/footer
86
87    let body = Container::new()
88        .with_position_and_size(0, 0, term_w.saturating_sub(2), body_h)
89        .with_layout_direction(LayoutDirection::Horizontal)
90        .with_column_gap(Gap::Pixels(2))
91        .with_padding(ContainerPadding::uniform(0));
92
93    // Panels are auto-sized from children, then clipped by the body container viewport.
94    // The text blocks have explicit sizes so word wrapping behaves predictably.
95    let panel_w = (term_w.saturating_sub(2))
96         .saturating_sub(2) // body column gap
97         / 2;
98    let panel_h = body_h;
99
100    // Leave space for: borders (2) + padding (2) => content width/height roughly -4.
101    let text_w = panel_w.saturating_sub(4).max(1);
102    let text_h = panel_h.saturating_sub(4).max(1);
103
104    let left_panel = Container::new()
105        .with_position_and_size(0, 0, panel_w, panel_h)
106        .with_layout_direction(LayoutDirection::Vertical)
107        .with_border()
108        .with_border_chars(BorderChars::single_line())
109        .with_border_color(ColorPair::new(Color::Red, Color::Black))
110        .with_title("Left")
111        .with_padding(ContainerPadding::uniform(1))
112        .add_child(
113            TextBlock::new(
114                text_w,
115                text_h,
116                "This demonstrates how Containers can be arranged side-by-side. \
117 They support borders, titles, padding, and child layout. \
118 Resize the terminal to see how clipping behaves.\
119 \r\rThis is a hard carriage returned line.",
120            )
121            .with_word_wrap(),
122        );
123
124    let right_panel = Container::new()
125        .with_position_and_size(0, 0, panel_w, panel_h)
126        .with_layout_direction(LayoutDirection::Vertical)
127        .with_border()
128        .with_border_chars(BorderChars::single_line())
129        .with_border_color(ColorPair::new(Color::Green, Color::Black))
130        .with_title("Right")
131        .with_padding(ContainerPadding::uniform(1))
132        .add_child(
133            TextBlock::new(
134                text_w,
135                text_h,
136                "Multiple widgets can coexist inside Container layouts. \
137 Each Container manages styling, while children provide content. \
138 This text is wrapped using TextBlock.",
139            )
140            .with_word_wrap(),
141        );
142
143    let body = body.add_child(left_panel).add_child(right_panel);
144
145    root.add_child(header).add_child(body).add_child(footer)
146}
Source

pub fn auto_sized(text: impl Into<String>) -> Self

Creates a TextBlock that sizes itself to fit the content

Source

pub fn auto_sized_with_word_wrap( text: impl Into<String>, max_width: u16, ) -> Self

Creates a TextBlock with word wrapping that sizes itself to fit.

Wraps text at word boundaries, then sizes the widget to fit the wrapped content.

Source

pub fn with_colors(self, colors: ColorPair) -> Self

Sets the text colors

Source

pub fn with_text_color(self, color: Color) -> Self

Sets just the text color

Source

pub fn with_wrap_mode(self, mode: TextWrapMode) -> Self

Sets how text should wrap

Source

pub fn with_word_wrap(self) -> Self

Enables word wrapping

Examples found in repository?
examples/widget_usage.rs (line 121)
41fn create_app_layout(term_w: u16, term_h: u16) -> Container {
42    // `ContainerPadding` is what the prelude exports (the underlying type is `Padding`).
43    use minui::widgets::ContainerPadding;
44
45    // A simple "fill the terminal" root. Children will be laid out inside it.
46    // We make it vertical with a row gap so sections are visually separated.
47    let root = Container::new()
48        .with_position_and_size(0, 0, term_w, term_h)
49        .with_layout_direction(LayoutDirection::Vertical)
50        .with_row_gap(Gap::Pixels(1))
51        .with_padding(ContainerPadding::uniform(1));
52
53    // Header: fixed height so it behaves like an app bar.
54    let header_h: u16 = 3;
55    let header = Container::new()
56        .with_position_and_size(0, 0, term_w.saturating_sub(2), header_h)
57        .with_layout_direction(LayoutDirection::Vertical)
58        .with_border()
59        .with_border_chars(BorderChars::double_line())
60        .with_border_color(ColorPair::new(Color::LightBlue, Color::Black))
61        .with_title("MinUI Widget Demo")
62        .with_title_alignment(TitleAlignment::Center)
63        .with_padding(ContainerPadding::symmetric(0, 1))
64        .add_child(Label::new("Press 'q' to quit").with_text_color(Color::Cyan));
65
66    // Footer: also fixed height.
67    let footer_h: u16 = 3;
68    let footer = Container::new()
69        .with_position_and_size(0, 0, term_w.saturating_sub(2), footer_h)
70        .with_layout_direction(LayoutDirection::Vertical)
71        .with_border()
72        .with_border_chars(BorderChars::single_line())
73        .with_border_color(ColorPair::new(Color::Yellow, Color::Black))
74        .with_padding(ContainerPadding::symmetric(0, 1))
75        .add_child(Label::new("Status: Ready • Press 'q' to quit").with_text_color(Color::Yellow));
76
77    // Body: fills the remaining space (best-effort). We size it explicitly so content has a
78    // stable viewport, but rely on Container layout for its children.
79    let body_h = term_h
80        .saturating_sub(1) // root padding top
81        .saturating_sub(1) // root padding bottom
82        .saturating_sub(header_h)
83        .saturating_sub(1) // root row gap between header/body
84        .saturating_sub(footer_h)
85        .saturating_sub(1); // root row gap between body/footer
86
87    let body = Container::new()
88        .with_position_and_size(0, 0, term_w.saturating_sub(2), body_h)
89        .with_layout_direction(LayoutDirection::Horizontal)
90        .with_column_gap(Gap::Pixels(2))
91        .with_padding(ContainerPadding::uniform(0));
92
93    // Panels are auto-sized from children, then clipped by the body container viewport.
94    // The text blocks have explicit sizes so word wrapping behaves predictably.
95    let panel_w = (term_w.saturating_sub(2))
96         .saturating_sub(2) // body column gap
97         / 2;
98    let panel_h = body_h;
99
100    // Leave space for: borders (2) + padding (2) => content width/height roughly -4.
101    let text_w = panel_w.saturating_sub(4).max(1);
102    let text_h = panel_h.saturating_sub(4).max(1);
103
104    let left_panel = Container::new()
105        .with_position_and_size(0, 0, panel_w, panel_h)
106        .with_layout_direction(LayoutDirection::Vertical)
107        .with_border()
108        .with_border_chars(BorderChars::single_line())
109        .with_border_color(ColorPair::new(Color::Red, Color::Black))
110        .with_title("Left")
111        .with_padding(ContainerPadding::uniform(1))
112        .add_child(
113            TextBlock::new(
114                text_w,
115                text_h,
116                "This demonstrates how Containers can be arranged side-by-side. \
117 They support borders, titles, padding, and child layout. \
118 Resize the terminal to see how clipping behaves.\
119 \r\rThis is a hard carriage returned line.",
120            )
121            .with_word_wrap(),
122        );
123
124    let right_panel = Container::new()
125        .with_position_and_size(0, 0, panel_w, panel_h)
126        .with_layout_direction(LayoutDirection::Vertical)
127        .with_border()
128        .with_border_chars(BorderChars::single_line())
129        .with_border_color(ColorPair::new(Color::Green, Color::Black))
130        .with_title("Right")
131        .with_padding(ContainerPadding::uniform(1))
132        .add_child(
133            TextBlock::new(
134                text_w,
135                text_h,
136                "Multiple widgets can coexist inside Container layouts. \
137 Each Container manages styling, while children provide content. \
138 This text is wrapped using TextBlock.",
139            )
140            .with_word_wrap(),
141        );
142
143    let body = body.add_child(left_panel).add_child(right_panel);
144
145    root.add_child(header).add_child(body).add_child(footer)
146}
Source

pub fn with_alignment( self, h_align: Alignment, v_align: VerticalAlignment, ) -> Self

Sets horizontal and vertical alignment

Source

pub fn set_text(&mut self, text: impl Into<String>)

Changes the text content.

Source

pub fn text(&self) -> &str

Returns the current text

Trait Implementations§

Source§

impl Widget for TextBlock

Source§

fn draw(&self, window: &mut dyn Window) -> Result<()>

Draws the widget to the window. Read more
Source§

fn get_size(&self) -> (u16, u16)

Returns the widget’s size as (width, height).
Source§

fn get_position(&self) -> (u16, u16)

Returns the widget’s position as (x, y). Read more
Source§

fn validate(&self, window_width: u16, window_height: u16) -> Result<()>

Checks if the widget fits in the given window size.
Source§

fn get_bounds(&self) -> (u16, u16, u16, u16)

Returns the widget’s bounding box as (x, y, width, height).
Source§

fn is_visible(&self) -> bool

Returns whether the widget is visible.
Source§

fn contains_point(&self, x: u16, y: u16) -> bool

Returns whether the point is inside the widget.
Source§

fn overlaps_with(&self, other: &dyn Widget) -> bool

Returns whether this widget overlaps with another.
Source§

fn get_area(&self) -> WidgetArea

Returns the area this widget occupies.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.