mirror of
https://github.com/ratatui-org/ratatui
synced 2024-11-10 07:04:17 +00:00
feat: impl WidgetRef for Fn(Rect, &mut Buffer)
This allows you to treat any function that takes a `Rect` and a mutable reference a `Buffer` as a widget in situations where you don't want to create a new type for a widget. Example: ```rust fn hello(area: Rect, buf: &mut Buffer) { Line::raw("Hello").render(area, buf); } frame.render_widget(&hello, frame.size()); frame.render_widget_ref(hello, frame.size()); ``` Related to: <https://forum.ratatui.rs/t/idea-functionwidget-was-thoughts-on-tui-react/59/2>
This commit is contained in:
parent
8061813f32
commit
f99c224fc1
1 changed files with 71 additions and 1 deletions
|
@ -245,6 +245,11 @@ pub trait StatefulWidget {
|
||||||
/// provided. This is a convenience approach to make it easier to attach child widgets to parent
|
/// provided. This is a convenience approach to make it easier to attach child widgets to parent
|
||||||
/// widgets. It allows you to render an optional widget by reference.
|
/// widgets. It allows you to render an optional widget by reference.
|
||||||
///
|
///
|
||||||
|
/// A blanket [implementation of `WidgetRef` for `Fn(Rect, &mut
|
||||||
|
/// Buffer)`](WidgetRef#impl-WidgetRef-for-F) is provided. This allows you to treat any function or
|
||||||
|
/// closure that takes a `Rect` and a mutable reference to a `Buffer` as a widget in situations
|
||||||
|
/// where you don't want to create a new type for a widget.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
@ -304,13 +309,40 @@ pub trait WidgetRef {
|
||||||
fn render_ref(&self, area: Rect, buf: &mut Buffer);
|
fn render_ref(&self, area: Rect, buf: &mut Buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This allows you to render a widget by reference.
|
// /// This allows you to render a widget by reference.
|
||||||
impl<W: WidgetRef> Widget for &W {
|
impl<W: WidgetRef> Widget for &W {
|
||||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||||
self.render_ref(area, buf);
|
self.render_ref(area, buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A blanket implementation of `WidgetRef` for `Fn(Rect, &mut Buffer)`.
|
||||||
|
///
|
||||||
|
/// This allows you to treat any function that takes a `Rect` and a mutable reference to a `Buffer`
|
||||||
|
/// as a widget in situations where you don't want to create a new type for a widget.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use ratatui::{prelude::*, widgets::*};
|
||||||
|
/// fn hello(area: Rect, buf: &mut Buffer) {
|
||||||
|
/// Line::raw("Hello").render(area, buf);
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// fn draw(mut frame: Frame) {
|
||||||
|
/// frame.render_widget(&hello, frame.size());
|
||||||
|
/// frame.render_widget_ref(hello, frame.size());
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
impl<F> WidgetRef for F
|
||||||
|
where
|
||||||
|
F: Fn(Rect, &mut Buffer),
|
||||||
|
{
|
||||||
|
fn render_ref(&self, area: Rect, buf: &mut Buffer) {
|
||||||
|
self(area, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A blanket implementation of `WidgetExt` for `Option<W>` where `W` implements `WidgetRef`.
|
/// A blanket implementation of `WidgetExt` for `Option<W>` where `W` implements `WidgetRef`.
|
||||||
///
|
///
|
||||||
/// This is a convenience implementation that makes it easy to attach child widgets to parent
|
/// This is a convenience implementation that makes it easy to attach child widgets to parent
|
||||||
|
@ -695,4 +727,42 @@ mod tests {
|
||||||
assert_eq!(buf, Buffer::with_lines(["hello world "]));
|
assert_eq!(buf, Buffer::with_lines(["hello world "]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod function_widget {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn widget_function(area: Rect, buf: &mut Buffer) {
|
||||||
|
"Hello".render(area, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn render(mut buf: Buffer) {
|
||||||
|
widget_function.render(buf.area, &mut buf);
|
||||||
|
assert_eq!(buf, Buffer::with_lines(["Hello "]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn render_ref(mut buf: Buffer) {
|
||||||
|
widget_function.render_ref(buf.area, &mut buf);
|
||||||
|
assert_eq!(buf, Buffer::with_lines(["Hello "]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn render_closure(mut buf: Buffer) {
|
||||||
|
let widget = |area: Rect, buf: &mut Buffer| {
|
||||||
|
"Hello".render(area, buf);
|
||||||
|
};
|
||||||
|
widget.render(buf.area, &mut buf);
|
||||||
|
assert_eq!(buf, Buffer::with_lines(["Hello "]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn render_closure_ref(mut buf: Buffer) {
|
||||||
|
let widget = |area: Rect, buf: &mut Buffer| {
|
||||||
|
"Hello".render(area, buf);
|
||||||
|
};
|
||||||
|
widget.render_ref(buf.area, &mut buf);
|
||||||
|
assert_eq!(buf, Buffer::with_lines(["Hello "]));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue