mirror of
https://github.com/ratatui/ratatui.git
synced 2025-10-02 15:25:54 +00:00

Added comprehensive state management examples covering both immutable and mutable patterns and documentation to help developers choose the right approach for their applications.
104 lines
3.5 KiB
Rust
104 lines
3.5 KiB
Rust
//! # Nested StatefulWidget Pattern
|
|
//!
|
|
//! This example demonstrates composing multiple `StatefulWidget`s in a parent-child hierarchy.
|
|
//! This pattern is ideal for complex applications where you need clean separation of concerns
|
|
//! and want to leverage the benefits of the StatefulWidget pattern at multiple levels.
|
|
//!
|
|
//! 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
|
|
//!
|
|
//! ## When to Use This Pattern
|
|
//!
|
|
//! - Complex applications with hierarchical state management needs
|
|
//! - When you want clean separation between widgets and their state
|
|
//! - Building composable widget systems
|
|
//! - Applications that need testable, reusable widget components
|
|
//!
|
|
//! ## Trade-offs
|
|
//!
|
|
//! **Pros:**
|
|
//! - Excellent separation of concerns
|
|
//! - Highly composable and reusable widgets
|
|
//! - Easy to test individual widgets and their state
|
|
//! - Scales well with application complexity
|
|
//! - Follows idiomatic Ratatui patterns
|
|
//!
|
|
//! **Cons:**
|
|
//! - More boilerplate code than simpler patterns
|
|
//! - Requires understanding of nested state management
|
|
//! - State structures can become complex
|
|
//! - May be overkill for simple applications
|
|
//!
|
|
//! ## Example Usage
|
|
//!
|
|
//! The parent `App` widget manages application-level state while delegating specific
|
|
//! functionality to child widgets like `Counter`. Each widget is responsible for its own
|
|
//! state type and rendering logic, making the system highly modular.
|
|
|
|
use ratatui::DefaultTerminal;
|
|
use ratatui::buffer::Buffer;
|
|
use ratatui::layout::Rect;
|
|
use ratatui::widgets::{StatefulWidget, Widget};
|
|
use ratatui_state_examples::is_exit_key_pressed;
|
|
|
|
/// Demonstrates the nested StatefulWidget pattern for mutable state management.
|
|
///
|
|
/// Creates a parent-child widget hierarchy using StatefulWidgets and runs the application loop,
|
|
/// updating the counter on each render cycle until the user exits.
|
|
fn main() -> color_eyre::Result<()> {
|
|
color_eyre::install()?;
|
|
ratatui::run(App::run)
|
|
}
|
|
|
|
/// The main application widget using the StatefulWidget pattern.
|
|
///
|
|
/// Demonstrates how to compose multiple StatefulWidgets together while coordinating
|
|
/// between different child widgets.
|
|
struct App;
|
|
|
|
impl App {
|
|
/// Run the application with the given terminal.
|
|
fn run(terminal: &mut DefaultTerminal) -> color_eyre::Result<()> {
|
|
let mut state = AppState { counter: 0 };
|
|
|
|
loop {
|
|
terminal.draw(|frame| frame.render_stateful_widget(App, frame.area(), &mut state))?;
|
|
if is_exit_key_pressed()? {
|
|
break Ok(());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Application state that contains all the state needed by the app and its child widgets.
|
|
///
|
|
/// Demonstrates how to organize hierarchical state in the StatefulWidget pattern.
|
|
struct AppState {
|
|
counter: usize,
|
|
}
|
|
|
|
impl StatefulWidget for App {
|
|
type State = AppState;
|
|
|
|
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
|
|
Counter.render(area, buf, &mut state.counter);
|
|
}
|
|
}
|
|
|
|
/// A counter widget that uses StatefulWidget for clean state separation.
|
|
///
|
|
/// Focuses purely on rendering logic and can be reused with different state instances.
|
|
struct Counter;
|
|
|
|
impl StatefulWidget for Counter {
|
|
type State = usize;
|
|
|
|
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
|
|
*state += 1;
|
|
format!("Counter: {state}").render(area, buf);
|
|
}
|
|
}
|