ratatui/
widgets.rs

1#![warn(missing_docs)]
2//! `widgets` is a collection of types that implement [`Widget`] or [`StatefulWidget`] or both.
3//!
4//! Widgets are created for each frame as they are consumed after rendered.
5//! They are not meant to be stored but used as *commands* to draw common figures in the UI.
6//!
7//! The available widgets are:
8//! - [`Block`]: a basic widget that draws a block with optional borders, titles and styles.
9//! - [`BarChart`]: displays multiple datasets as bars with optional grouping.
10//! - [`calendar::Monthly`]: displays a single month.
11//! - [`Canvas`]: draws arbitrary shapes using drawing characters.
12//! - [`Chart`]: displays multiple datasets as a lines or scatter graph.
13//! - [`Clear`]: clears the area it occupies. Useful to render over previously drawn widgets.
14//! - [`Gauge`]: displays progress percentage using block characters.
15//! - [`LineGauge`]: display progress as a line.
16//! - [`List`]: displays a list of items and allows selection.
17//! - [`Paragraph`]: displays a paragraph of optionally styled and wrapped text.
18//! - [`Scrollbar`]: displays a scrollbar.
19//! - [`Sparkline`]: display a single data set as a sparkline.
20//! - [`Table`]: displays multiple rows and columns in a grid and allows selection.
21//! - [`Tabs`]: displays a tab bar and allows selection.
22//!
23//! [`Canvas`]: crate::widgets::canvas::Canvas
24mod barchart;
25pub mod block;
26mod borders;
27#[cfg(feature = "widget-calendar")]
28pub mod calendar;
29pub mod canvas;
30mod chart;
31mod clear;
32mod gauge;
33mod list;
34mod logo;
35mod paragraph;
36mod reflow;
37mod scrollbar;
38mod sparkline;
39mod table;
40mod tabs;
41
42pub use self::{
43    barchart::{Bar, BarChart, BarGroup},
44    block::{Block, BorderType, Padding},
45    borders::*,
46    chart::{Axis, Chart, Dataset, GraphType, LegendPosition},
47    clear::Clear,
48    gauge::{Gauge, LineGauge},
49    list::{List, ListDirection, ListItem, ListState},
50    logo::{RatatuiLogo, Size as RatatuiLogoSize},
51    paragraph::{Paragraph, Wrap},
52    scrollbar::{ScrollDirection, Scrollbar, ScrollbarOrientation, ScrollbarState},
53    sparkline::{RenderDirection, Sparkline, SparklineBar},
54    table::{Cell, HighlightSpacing, Row, Table, TableState},
55    tabs::Tabs,
56};
57use crate::{buffer::Buffer, layout::Rect, style::Style};
58
59/// A `Widget` is a type that can be drawn on a [`Buffer`] in a given [`Rect`].
60///
61/// Prior to Ratatui 0.26.0, widgets generally were created for each frame as they were consumed
62/// during rendering. This meant that they were not meant to be stored but used as *commands* to
63/// draw common figures in the UI.
64///
65/// Starting with Ratatui 0.26.0, all the internal widgets implement Widget for a reference to
66/// themselves. This allows you to store a reference to a widget and render it later. Widget crates
67/// should consider also doing this to allow for more flexibility in how widgets are used.
68///
69/// In Ratatui 0.26.0, we also added an unstable [`WidgetRef`] trait and implemented this on all the
70/// internal widgets. In addition to the above benefit of rendering references to widgets, this also
71/// allows you to render boxed widgets. This is useful when you want to store a collection of
72/// widgets with different types. You can then iterate over the collection and render each widget.
73/// See <https://github.com/ratatui/ratatui/issues/1287> for more information.
74///
75/// In general where you expect a widget to immutably work on its data, we recommended to implement
76/// `Widget` for a reference to the widget (`impl Widget for &MyWidget`). If you need to store state
77/// between draw calls, implement `StatefulWidget` if you want the Widget to be immutable, or
78/// implement `Widget` for a mutable reference to the widget (`impl Widget for &mut MyWidget`) if
79/// you want the widget to be mutable. The mutable widget pattern is used infrequently in apps, but
80/// can be quite useful.
81///
82/// A blanket implementation of `Widget` for `&W` where `W` implements `WidgetRef` is provided.
83/// Widget is also implemented for `&str` and `String` types.
84///
85/// # Examples
86///
87/// ```rust,no_run
88/// use ratatui::{
89///     backend::TestBackend,
90///     widgets::{Clear, Widget},
91///     Terminal,
92/// };
93/// # let backend = TestBackend::new(5, 5);
94/// # let mut terminal = Terminal::new(backend).unwrap();
95///
96/// terminal.draw(|frame| {
97///     frame.render_widget(Clear, frame.area());
98/// });
99/// ```
100///
101/// It's common to render widgets inside other widgets:
102///
103/// ```rust
104/// use ratatui::{buffer::Buffer, layout::Rect, text::Line, widgets::Widget};
105///
106/// struct MyWidget;
107///
108/// impl Widget for MyWidget {
109///     fn render(self, area: Rect, buf: &mut Buffer) {
110///         Line::raw("Hello").render(area, buf);
111///     }
112/// }
113/// ```
114pub trait Widget {
115    /// Draws the current state of the widget in the given buffer. That is the only method required
116    /// to implement a custom widget.
117    fn render(self, area: Rect, buf: &mut Buffer)
118    where
119        Self: Sized;
120}
121
122/// A `StatefulWidget` is a widget that can take advantage of some local state to remember things
123/// between two draw calls.
124///
125/// Most widgets can be drawn directly based on the input parameters. However, some features may
126/// require some kind of associated state to be implemented.
127///
128/// For example, the [`List`] widget can highlight the item currently selected. This can be
129/// translated in an offset, which is the number of elements to skip in order to have the selected
130/// item within the viewport currently allocated to this widget. The widget can therefore only
131/// provide the following behavior: whenever the selected item is out of the viewport scroll to a
132/// predefined position (making the selected item the last viewable item or the one in the middle
133/// for example). Nonetheless, if the widget has access to the last computed offset then it can
134/// implement a natural scrolling experience where the last offset is reused until the selected
135/// item is out of the viewport.
136///
137/// ## Examples
138///
139/// ```rust,no_run
140/// use std::io;
141///
142/// use ratatui::{
143///     backend::TestBackend,
144///     widgets::{List, ListItem, ListState, StatefulWidget, Widget},
145///     Terminal,
146/// };
147///
148/// // Let's say we have some events to display.
149/// struct Events {
150///     // `items` is the state managed by your application.
151///     items: Vec<String>,
152///     // `state` is the state that can be modified by the UI. It stores the index of the selected
153///     // item as well as the offset computed during the previous draw call (used to implement
154///     // natural scrolling).
155///     state: ListState,
156/// }
157///
158/// impl Events {
159///     fn new(items: Vec<String>) -> Events {
160///         Events {
161///             items,
162///             state: ListState::default(),
163///         }
164///     }
165///
166///     pub fn set_items(&mut self, items: Vec<String>) {
167///         self.items = items;
168///         // We reset the state as the associated items have changed. This effectively reset
169///         // the selection as well as the stored offset.
170///         self.state = ListState::default();
171///     }
172///
173///     // Select the next item. This will not be reflected until the widget is drawn in the
174///     // `Terminal::draw` callback using `Frame::render_stateful_widget`.
175///     pub fn next(&mut self) {
176///         let i = match self.state.selected() {
177///             Some(i) => {
178///                 if i >= self.items.len() - 1 {
179///                     0
180///                 } else {
181///                     i + 1
182///                 }
183///             }
184///             None => 0,
185///         };
186///         self.state.select(Some(i));
187///     }
188///
189///     // Select the previous item. This will not be reflected until the widget is drawn in the
190///     // `Terminal::draw` callback using `Frame::render_stateful_widget`.
191///     pub fn previous(&mut self) {
192///         let i = match self.state.selected() {
193///             Some(i) => {
194///                 if i == 0 {
195///                     self.items.len() - 1
196///                 } else {
197///                     i - 1
198///                 }
199///             }
200///             None => 0,
201///         };
202///         self.state.select(Some(i));
203///     }
204///
205///     // Unselect the currently selected item if any. The implementation of `ListState` makes
206///     // sure that the stored offset is also reset.
207///     pub fn unselect(&mut self) {
208///         self.state.select(None);
209///     }
210/// }
211///
212/// # let backend = TestBackend::new(5, 5);
213/// # let mut terminal = Terminal::new(backend).unwrap();
214///
215/// let mut events = Events::new(vec![String::from("Item 1"), String::from("Item 2")]);
216///
217/// loop {
218///     terminal.draw(|f| {
219///         // The items managed by the application are transformed to something
220///         // that is understood by ratatui.
221///         let items: Vec<ListItem> = events
222///             .items
223///             .iter()
224///             .map(|i| ListItem::new(i.as_str()))
225///             .collect();
226///         // The `List` widget is then built with those items.
227///         let list = List::new(items);
228///         // Finally the widget is rendered using the associated state. `events.state` is
229///         // effectively the only thing that we will "remember" from this draw call.
230///         f.render_stateful_widget(list, f.size(), &mut events.state);
231///     });
232///
233///     // In response to some input events or an external http request or whatever:
234///     events.next();
235/// }
236/// ```
237pub trait StatefulWidget {
238    /// State associated with the stateful widget.
239    ///
240    /// If you don't need this then you probably want to implement [`Widget`] instead.
241    type State;
242    /// Draws the current state of the widget in the given buffer. That is the only method required
243    /// to implement a custom stateful widget.
244    fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State);
245}
246
247/// A `WidgetRef` is a trait that allows rendering a widget by reference.
248///
249/// This trait is useful when you want to store a reference to a widget and render it later. It also
250/// allows you to render boxed widgets.
251///
252/// Boxed widgets allow you to store widgets with a type that is not known at compile time. This is
253/// useful when you want to store a collection of widgets with different types. You can then iterate
254/// over the collection and render each widget.
255///
256/// This trait was introduced in Ratatui 0.26.0 and is implemented for all the internal widgets. It
257/// is currently marked as unstable as we are still evaluating the API and may make changes in the
258/// future. See <https://github.com/ratatui/ratatui/issues/1287> for more information.
259///
260/// A blanket implementation of `Widget` for `&W` where `W` implements `WidgetRef` is provided.
261///
262/// A blanket implementation of `WidgetRef` for `Option<W>` where `W` implements `WidgetRef` is
263/// provided. This is a convenience approach to make it easier to attach child widgets to parent
264/// widgets. It allows you to render an optional widget by reference.
265///
266/// # Examples
267///
268/// ```rust
269/// # #[cfg(feature = "unstable-widget-ref")] {
270/// use ratatui::{
271///     buffer::Buffer,
272///     layout::Rect,
273///     text::Line,
274///     widgets::{Widget, WidgetRef},
275/// };
276///
277/// struct Greeting;
278///
279/// struct Farewell;
280///
281/// impl WidgetRef for Greeting {
282///     fn render_ref(&self, area: Rect, buf: &mut Buffer) {
283///         Line::raw("Hello").render(area, buf);
284///     }
285/// }
286///
287/// /// Only needed for backwards compatibility
288/// impl Widget for Greeting {
289///     fn render(self, area: Rect, buf: &mut Buffer) {
290///         self.render_ref(area, buf);
291///     }
292/// }
293///
294/// impl WidgetRef for Farewell {
295///     fn render_ref(&self, area: Rect, buf: &mut Buffer) {
296///         Line::raw("Goodbye").right_aligned().render(area, buf);
297///     }
298/// }
299///
300/// /// Only needed for backwards compatibility
301/// impl Widget for Farewell {
302///     fn render(self, area: Rect, buf: &mut Buffer) {
303///         self.render_ref(area, buf);
304///     }
305/// }
306///
307/// # fn render(area: Rect, buf: &mut Buffer) {
308/// let greeting = Greeting;
309/// let farewell = Farewell;
310///
311/// // these calls do not consume the widgets, so they can be used again later
312/// greeting.render_ref(area, buf);
313/// farewell.render_ref(area, buf);
314///
315/// // a collection of widgets with different types
316/// let widgets: Vec<Box<dyn WidgetRef>> = vec![Box::new(greeting), Box::new(farewell)];
317/// for widget in widgets {
318///     widget.render_ref(area, buf);
319/// }
320/// # }
321/// # }
322/// ```
323#[instability::unstable(feature = "widget-ref")]
324pub trait WidgetRef {
325    /// Draws the current state of the widget in the given buffer. That is the only method required
326    /// to implement a custom widget.
327    fn render_ref(&self, area: Rect, buf: &mut Buffer);
328}
329
330/// This allows you to render a widget by reference.
331impl<W: WidgetRef> Widget for &W {
332    fn render(self, area: Rect, buf: &mut Buffer) {
333        self.render_ref(area, buf);
334    }
335}
336
337/// A blanket implementation of `WidgetExt` for `Option<W>` where `W` implements `WidgetRef`.
338///
339/// This is a convenience implementation that makes it easy to attach child widgets to parent
340/// widgets. It allows you to render an optional widget by reference.
341///
342/// The internal widgets use this pattern to render the optional `Block` widgets that are included
343/// on most widgets.
344/// Blanket implementation of `WidgetExt` for `Option<W>` where `W` implements `WidgetRef`.
345///
346/// # Examples
347///
348/// ```rust
349/// # #[cfg(feature = "unstable-widget-ref")] {
350/// use ratatui::{
351///     buffer::Buffer,
352///     layout::Rect,
353///     text::Line,
354///     widgets::{Widget, WidgetRef},
355/// };
356///
357/// struct Parent {
358///     child: Option<Child>,
359/// }
360///
361/// struct Child;
362///
363/// impl WidgetRef for Child {
364///     fn render_ref(&self, area: Rect, buf: &mut Buffer) {
365///         Line::raw("Hello from child").render(area, buf);
366///     }
367/// }
368///
369/// impl WidgetRef for Parent {
370///     fn render_ref(&self, area: Rect, buf: &mut Buffer) {
371///         self.child.render_ref(area, buf);
372///     }
373/// }
374/// # }
375/// ```
376impl<W: WidgetRef> WidgetRef for Option<W> {
377    fn render_ref(&self, area: Rect, buf: &mut Buffer) {
378        if let Some(widget) = self {
379            widget.render_ref(area, buf);
380        }
381    }
382}
383
384/// A `StatefulWidgetRef` is a trait that allows rendering a stateful widget by reference.
385///
386/// This is the stateful equivalent of `WidgetRef`. It is useful when you want to store a reference
387/// to a stateful widget and render it later. It also allows you to render boxed stateful widgets.
388///
389/// This trait was introduced in Ratatui 0.26.0 and is implemented for all the internal stateful
390/// widgets. It is currently marked as unstable as we are still evaluating the API and may make
391/// changes in the future. See <https://github.com/ratatui/ratatui/issues/1287> for more
392/// information.
393///
394/// A blanket implementation of `StatefulWidget` for `&W` where `W` implements `StatefulWidgetRef`
395/// is provided.
396///
397/// See the documentation for [`WidgetRef`] for more information on boxed widgets.
398/// See the documentation for [`StatefulWidget`] for more information on stateful widgets.
399///
400/// # Examples
401///
402/// ```rust
403/// # #[cfg(feature = "unstable-widget-ref")] {
404/// use ratatui::{
405///     buffer::Buffer,
406///     layout::Rect,
407///     style::Stylize,
408///     text::Line,
409///     widgets::{StatefulWidget, StatefulWidgetRef, Widget},
410/// };
411///
412/// struct PersonalGreeting;
413///
414/// impl StatefulWidgetRef for PersonalGreeting {
415///     type State = String;
416///     fn render_ref(&self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
417///         Line::raw(format!("Hello {}", state)).render(area, buf);
418///     }
419/// }
420///
421/// impl StatefulWidget for PersonalGreeting {
422///     type State = String;
423///     fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
424///         (&self).render_ref(area, buf, state);
425///     }
426/// }
427///
428/// fn render(area: Rect, buf: &mut Buffer) {
429///     let widget = PersonalGreeting;
430///     let mut state = "world".to_string();
431///     widget.render(area, buf, &mut state);
432/// }
433/// # }
434/// ```
435#[instability::unstable(feature = "widget-ref")]
436pub trait StatefulWidgetRef {
437    /// State associated with the stateful widget.
438    ///
439    /// If you don't need this then you probably want to implement [`WidgetRef`] instead.
440    type State;
441    /// Draws the current state of the widget in the given buffer. That is the only method required
442    /// to implement a custom stateful widget.
443    fn render_ref(&self, area: Rect, buf: &mut Buffer, state: &mut Self::State);
444}
445
446// Note: while StatefulWidgetRef is marked as unstable, the blanket implementation of StatefulWidget
447// cannot be implemented as W::State is effectively pub(crate) and not accessible from outside the
448// crate. Once stabilized, this blanket implementation can be added and the specific implementations
449// on Table and List can be removed.
450//
451// /// Blanket implementation of `StatefulWidget` for `&W` where `W` implements `StatefulWidgetRef`.
452// ///
453// /// This allows you to render a stateful widget by reference.
454// impl<W: StatefulWidgetRef> StatefulWidget for &W {
455//     type State = W::State;
456//     fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
457//         StatefulWidgetRef::render_ref(self, area, buf, state);
458//     }
459// }
460
461/// Renders a string slice as a widget.
462///
463/// This implementation allows a string slice (`&str`) to act as a widget, meaning it can be drawn
464/// onto a [`Buffer`] in a specified [`Rect`]. The slice represents a static string which can be
465/// rendered by reference, thereby avoiding the need for string cloning or ownership transfer when
466/// drawing the text to the screen.
467impl Widget for &str {
468    fn render(self, area: Rect, buf: &mut Buffer) {
469        self.render_ref(area, buf);
470    }
471}
472
473/// Provides the ability to render a string slice by reference.
474///
475/// This trait implementation ensures that a string slice, which is an immutable view over a
476/// `String`, can be drawn on demand without requiring ownership of the string itself. It utilizes
477/// the default text style when rendering onto the provided [`Buffer`] at the position defined by
478/// [`Rect`].
479impl WidgetRef for &str {
480    fn render_ref(&self, area: Rect, buf: &mut Buffer) {
481        buf.set_stringn(area.x, area.y, self, area.width as usize, Style::new());
482    }
483}
484
485/// Renders a `String` object as a widget.
486///
487/// This implementation enables an owned `String` to be treated as a widget, which can be rendered
488/// on a [`Buffer`] within the bounds of a given [`Rect`].
489impl Widget for String {
490    fn render(self, area: Rect, buf: &mut Buffer) {
491        self.render_ref(area, buf);
492    }
493}
494
495/// Provides the ability to render a `String` by reference.
496///
497/// This trait allows for a `String` to be rendered onto the [`Buffer`], similarly using the default
498/// style settings. It ensures that an owned `String` can be rendered efficiently by reference,
499/// without the need to give up ownership of the underlying text.
500impl WidgetRef for String {
501    fn render_ref(&self, area: Rect, buf: &mut Buffer) {
502        buf.set_stringn(area.x, area.y, self, area.width as usize, Style::new());
503    }
504}
505
506#[cfg(test)]
507mod tests {
508    use rstest::{fixture, rstest};
509
510    use super::*;
511    use crate::text::Line;
512
513    #[fixture]
514    fn buf() -> Buffer {
515        Buffer::empty(Rect::new(0, 0, 20, 1))
516    }
517
518    mod widget {
519        use super::*;
520
521        struct Greeting;
522
523        impl Widget for Greeting {
524            fn render(self, area: Rect, buf: &mut Buffer) {
525                Line::from("Hello").render(area, buf);
526            }
527        }
528
529        #[rstest]
530        fn render(mut buf: Buffer) {
531            let widget = Greeting;
532            widget.render(buf.area, &mut buf);
533            assert_eq!(buf, Buffer::with_lines(["Hello               "]));
534        }
535    }
536
537    mod widget_ref {
538        use super::*;
539
540        struct Greeting;
541        struct Farewell;
542
543        impl WidgetRef for Greeting {
544            fn render_ref(&self, area: Rect, buf: &mut Buffer) {
545                Line::from("Hello").render(area, buf);
546            }
547        }
548
549        impl WidgetRef for Farewell {
550            fn render_ref(&self, area: Rect, buf: &mut Buffer) {
551                Line::from("Goodbye").right_aligned().render(area, buf);
552            }
553        }
554
555        #[rstest]
556        fn render_ref(mut buf: Buffer) {
557            let widget = Greeting;
558            widget.render_ref(buf.area, &mut buf);
559            assert_eq!(buf, Buffer::with_lines(["Hello               "]));
560        }
561
562        /// Ensure that the blanket implementation of `Widget` for `&W` where `W` implements
563        /// `WidgetRef` works as expected.
564        #[rstest]
565        fn blanket_render(mut buf: Buffer) {
566            let widget = &Greeting;
567            widget.render(buf.area, &mut buf);
568            assert_eq!(buf, Buffer::with_lines(["Hello               "]));
569        }
570
571        #[rstest]
572        fn box_render_ref(mut buf: Buffer) {
573            let widget: Box<dyn WidgetRef> = Box::new(Greeting);
574            widget.render_ref(buf.area, &mut buf);
575            assert_eq!(buf, Buffer::with_lines(["Hello               "]));
576        }
577
578        #[rstest]
579        fn vec_box_render(mut buf: Buffer) {
580            let widgets: Vec<Box<dyn WidgetRef>> = vec![Box::new(Greeting), Box::new(Farewell)];
581            for widget in widgets {
582                widget.render_ref(buf.area, &mut buf);
583            }
584            assert_eq!(buf, Buffer::with_lines(["Hello        Goodbye"]));
585        }
586    }
587
588    #[fixture]
589    fn state() -> String {
590        "world".to_string()
591    }
592
593    mod stateful_widget {
594        use super::*;
595
596        struct PersonalGreeting;
597
598        impl StatefulWidget for PersonalGreeting {
599            type State = String;
600            fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
601                Line::from(format!("Hello {state}")).render(area, buf);
602            }
603        }
604
605        #[rstest]
606        fn render(mut buf: Buffer, mut state: String) {
607            let widget = PersonalGreeting;
608            widget.render(buf.area, &mut buf, &mut state);
609            assert_eq!(buf, Buffer::with_lines(["Hello world         "]));
610        }
611    }
612
613    mod stateful_widget_ref {
614        use super::*;
615
616        struct PersonalGreeting;
617
618        impl StatefulWidgetRef for PersonalGreeting {
619            type State = String;
620            fn render_ref(&self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
621                Line::from(format!("Hello {state}")).render(area, buf);
622            }
623        }
624
625        #[rstest]
626        fn render_ref(mut buf: Buffer, mut state: String) {
627            let widget = PersonalGreeting;
628            widget.render_ref(buf.area, &mut buf, &mut state);
629            assert_eq!(buf, Buffer::with_lines(["Hello world         "]));
630        }
631
632        // Note this cannot be tested until the blanket implementation of StatefulWidget for &W
633        // where W implements StatefulWidgetRef is added. (see the comment in the blanket
634        // implementation for more).
635        // /// This test is to ensure that the blanket implementation of `StatefulWidget` for `&W`
636        // where /// `W` implements `StatefulWidgetRef` works as expected.
637        // #[rstest]
638        // fn stateful_widget_blanket_render(mut buf: Buffer, mut state: String) {
639        //     let widget = &PersonalGreeting;
640        //     widget.render(buf.area, &mut buf, &mut state);
641        //     assert_eq!(buf, Buffer::with_lines(["Hello world         "]));
642        // }
643
644        #[rstest]
645        fn box_render_render(mut buf: Buffer, mut state: String) {
646            let widget = Box::new(PersonalGreeting);
647            widget.render_ref(buf.area, &mut buf, &mut state);
648            assert_eq!(buf, Buffer::with_lines(["Hello world         "]));
649        }
650    }
651
652    mod option_widget_ref {
653        use super::*;
654
655        struct Greeting;
656
657        impl WidgetRef for Greeting {
658            fn render_ref(&self, area: Rect, buf: &mut Buffer) {
659                Line::from("Hello").render(area, buf);
660            }
661        }
662
663        #[rstest]
664        fn render_ref_some(mut buf: Buffer) {
665            let widget = Some(Greeting);
666            widget.render_ref(buf.area, &mut buf);
667            assert_eq!(buf, Buffer::with_lines(["Hello               "]));
668        }
669
670        #[rstest]
671        fn render_ref_none(mut buf: Buffer) {
672            let widget: Option<Greeting> = None;
673            widget.render_ref(buf.area, &mut buf);
674            assert_eq!(buf, Buffer::with_lines(["                    "]));
675        }
676    }
677
678    mod str {
679        use super::*;
680
681        #[rstest]
682        fn render(mut buf: Buffer) {
683            "hello world".render(buf.area, &mut buf);
684            assert_eq!(buf, Buffer::with_lines(["hello world         "]));
685        }
686
687        #[rstest]
688        fn render_area(mut buf: Buffer) {
689            let area = Rect::new(buf.area.x, buf.area.y, 11, buf.area.height);
690            "hello world, just hello".render(area, &mut buf);
691            assert_eq!(buf, Buffer::with_lines(["hello world         "]));
692        }
693
694        #[rstest]
695        fn render_ref(mut buf: Buffer) {
696            "hello world".render_ref(buf.area, &mut buf);
697            assert_eq!(buf, Buffer::with_lines(["hello world         "]));
698        }
699
700        #[rstest]
701        fn option_render(mut buf: Buffer) {
702            Some("hello world").render(buf.area, &mut buf);
703            assert_eq!(buf, Buffer::with_lines(["hello world         "]));
704        }
705
706        #[rstest]
707        fn option_render_ref(mut buf: Buffer) {
708            Some("hello world").render_ref(buf.area, &mut buf);
709            assert_eq!(buf, Buffer::with_lines(["hello world         "]));
710        }
711    }
712
713    mod string {
714        use super::*;
715        #[rstest]
716        fn render(mut buf: Buffer) {
717            String::from("hello world").render(buf.area, &mut buf);
718            assert_eq!(buf, Buffer::with_lines(["hello world         "]));
719        }
720
721        #[rstest]
722        fn render_area(mut buf: Buffer) {
723            let area = Rect::new(buf.area.x, buf.area.y, 11, buf.area.height);
724            String::from("hello world, just hello").render(area, &mut buf);
725            assert_eq!(buf, Buffer::with_lines(["hello world         "]));
726        }
727
728        #[rstest]
729        fn render_ref(mut buf: Buffer) {
730            String::from("hello world").render_ref(buf.area, &mut buf);
731            assert_eq!(buf, Buffer::with_lines(["hello world         "]));
732        }
733
734        #[rstest]
735        fn option_render(mut buf: Buffer) {
736            Some(String::from("hello world")).render(buf.area, &mut buf);
737            assert_eq!(buf, Buffer::with_lines(["hello world         "]));
738        }
739
740        #[rstest]
741        fn option_render_ref(mut buf: Buffer) {
742            Some(String::from("hello world")).render_ref(buf.area, &mut buf);
743            assert_eq!(buf, Buffer::with_lines(["hello world         "]));
744        }
745    }
746}