retroglyph_widgets/widget/mod.rs
1//! `Widget`/`StatefulWidget` structs: one file per widget, each a builder
2//! that owns its own drawing logic.
3//!
4//! `new()` takes only the arguments a widget cannot mean anything without
5//! (the content: a value, a label, a slice of samples/rows). Every other
6//! knob -- styles, offsets, titles -- has a default and is set through a
7//! chainable `#[must_use] fn field(mut self, ...) -> Self` method, the same
8//! shape as [`Panel::title`] or [`Log::offset`]. See `crates/widgets/AGENTS.md`
9//! for the rule this is enforcing and why.
10//!
11//! A few widgets share logic: [`Gauge`] and [`StatBar`] both delegate to a
12//! crate-private `bar` module, and [`Sparkline`]/[`Gauge`]/[`StatBar`] all
13//! use [`Meter`] for their ratio-to-color ramp. [`Paragraph`] (behind the
14//! `egc` feature) additionally implements [`Measure`], since it needs
15//! `retroglyph_core::layout::TextLayout`'s grapheme-aware word-wrap to
16//! report a height before rendering.
17use retroglyph_core::{Backend, Rect, Terminal};
18
19mod bar;
20mod box_border;
21mod button;
22mod gauge;
23mod list;
24mod log;
25mod meter;
26mod modal;
27mod panel;
28#[cfg(feature = "egc")]
29mod paragraph;
30mod print_line;
31mod progress_bar;
32mod scrollbar;
33mod sparkline;
34mod stat_bar;
35mod table;
36mod tabs;
37mod text;
38mod window;
39
40pub use box_border::BoxBorder;
41pub use button::Button;
42pub use gauge::Gauge;
43pub use list::List;
44pub use log::Log;
45pub use meter::Meter;
46pub use modal::Modal;
47pub use panel::Panel;
48#[cfg(feature = "egc")]
49pub use paragraph::Paragraph;
50pub use print_line::PrintLine;
51pub use progress_bar::ProgressBar;
52pub use scrollbar::Scrollbar;
53pub use sparkline::Sparkline;
54pub use stat_bar::StatBar;
55pub use table::Table;
56pub use tabs::Tabs;
57pub use text::Text;
58
59/// A type that draws itself into a terminal area, without retaining any
60/// state — the minimal shape shared by every widget-like consumer.
61pub trait Widget<B: Backend> {
62 /// Draw this widget into `area`.
63 fn render(self, area: Rect, term: &mut Terminal<B>);
64}
65
66/// Like [`Widget`], but for widgets that read (and may update) externally
67/// owned state — a selection index, a scroll offset — that outlives a
68/// single render call. See [`crate::ListState`].
69pub trait StatefulWidget<B: Backend> {
70 /// The externally owned state this widget reads and/or updates while
71 /// rendering.
72 type State;
73
74 /// Draw this widget into `area`, using and/or updating `state`.
75 fn render(self, area: Rect, term: &mut Terminal<B>, state: &mut Self::State);
76}
77
78/// A widget that can report the height it needs for a given width, before
79/// ever being rendered.
80///
81/// Lets a caller size a pane to fit content (e.g. a wrapped `Paragraph`,
82/// behind the `egc` feature) instead of guessing a fixed height up front.
83/// Independent of any [`Backend`]: sizing is pure content math, not drawing.
84pub trait Measure {
85 /// The number of rows this widget would need to render at `width`
86 /// columns.
87 fn height_for(&self, width: u16) -> u16;
88}