docs: add widget-ref-container example (#1603)
Implements ideas alluded to by <https://discord.com/channels/1070692720437383208/1072907135664529508/1323061053990637640> and followup conversations.
This commit is contained in:
@@ -254,6 +254,11 @@ name = "widget_impl"
|
||||
required-features = ["crossterm", "unstable-widget-ref"]
|
||||
doc-scrape-examples = true
|
||||
|
||||
[[example]]
|
||||
name = "widget-ref-container"
|
||||
required-features = ["crossterm", "unstable-widget-ref"]
|
||||
doc-scrape-examples = true
|
||||
|
||||
[[test]]
|
||||
name = "state_serde"
|
||||
required-features = ["serde"]
|
||||
|
||||
92
ratatui/examples/widget-ref-container.rs
Normal file
92
ratatui/examples/widget-ref-container.rs
Normal file
@@ -0,0 +1,92 @@
|
||||
//! An example of how to use [`WidgetRef`] to store heterogeneous widgets in a container.
|
||||
//!
|
||||
//! This example creates a `StackContainer` widget that can hold any number of widgets of different
|
||||
//! types. It creates two widgets, `Greeting` and `Farewell`, and stores them in a `StackContainer`
|
||||
//! with a vertical layout. The `StackContainer` widget renders each of its child widgets in the
|
||||
//! order they were added.
|
||||
//!
|
||||
//! `Greetings` and `Farewell` both implement the Widget trait on references to themselves, which
|
||||
//! triggers the blanket implementation of [`WidgetRef`] for them. This allows them to be stored in
|
||||
//! the `StackContainer` in a boxed form.
|
||||
//!
|
||||
//! This example runs with the Ratatui library code in the branch that you are currently reading.
|
||||
//! See the [`latest`] branch for the code which works with the most recent Ratatui release.
|
||||
//!
|
||||
//! [`latest`]: https://github.com/ratatui/ratatui/tree/latest
|
||||
|
||||
use std::iter::zip;
|
||||
|
||||
use color_eyre::Result;
|
||||
use crossterm::event;
|
||||
use ratatui::{
|
||||
buffer::Buffer,
|
||||
layout::{Constraint, Direction, Layout, Rect},
|
||||
widgets::{Block, Paragraph, Widget, WidgetRef},
|
||||
DefaultTerminal, Frame,
|
||||
};
|
||||
|
||||
fn main() -> Result<()> {
|
||||
color_eyre::install()?;
|
||||
let terminal = ratatui::init();
|
||||
let result = run(terminal);
|
||||
ratatui::restore();
|
||||
result
|
||||
}
|
||||
|
||||
fn run(mut terminal: DefaultTerminal) -> Result<()> {
|
||||
loop {
|
||||
terminal.draw(render)?;
|
||||
if matches!(event::read()?, event::Event::Key(_)) {
|
||||
break Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn render(frame: &mut Frame) {
|
||||
let container = StackContainer {
|
||||
direction: Direction::Vertical,
|
||||
widgets: vec![
|
||||
(Box::new(&Greeting), Constraint::Percentage(50)),
|
||||
(Box::new(&Farewell), Constraint::Percentage(50)),
|
||||
],
|
||||
};
|
||||
frame.render_widget(&container, frame.area());
|
||||
}
|
||||
|
||||
struct Greeting;
|
||||
|
||||
impl Widget for &Greeting {
|
||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
Paragraph::new("Hello")
|
||||
.block(Block::bordered())
|
||||
.render(area, buf);
|
||||
}
|
||||
}
|
||||
|
||||
struct Farewell;
|
||||
|
||||
impl Widget for &Farewell {
|
||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
Paragraph::new("Goodbye")
|
||||
.block(Block::bordered())
|
||||
.render(area, buf);
|
||||
}
|
||||
}
|
||||
|
||||
struct StackContainer {
|
||||
direction: Direction,
|
||||
widgets: Vec<(Box<dyn WidgetRef>, Constraint)>,
|
||||
}
|
||||
|
||||
impl Widget for &StackContainer {
|
||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
let layout = Layout::default()
|
||||
.direction(self.direction)
|
||||
.constraints(self.widgets.iter().map(|(_, constraint)| *constraint))
|
||||
.split(area);
|
||||
let widgets = self.widgets.iter().map(|(widget, _)| widget);
|
||||
for (widget, area) in zip(widgets, layout.iter()) {
|
||||
widget.render_ref(*area, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user