ratatui/
widgets.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
#![warn(missing_docs)]
//! `widgets` is a collection of types that implement [`Widget`] or [`StatefulWidget`] or both.
//!
//! Widgets are created for each frame as they are consumed after rendered.
//! They are not meant to be stored but used as *commands* to draw common figures in the UI.
//!
//! The available widgets are:
//! - [`Block`]: a basic widget that draws a block with optional borders, titles and styles.
//! - [`BarChart`]: displays multiple datasets as bars with optional grouping.
//! - [`calendar::Monthly`]: displays a single month.
//! - [`Canvas`]: draws arbitrary shapes using drawing characters.
//! - [`Chart`]: displays multiple datasets as a lines or scatter graph.
//! - [`Clear`]: clears the area it occupies. Useful to render over previously drawn widgets.
//! - [`Gauge`]: displays progress percentage using block characters.
//! - [`LineGauge`]: display progress as a line.
//! - [`List`]: displays a list of items and allows selection.
//! - [`Paragraph`]: displays a paragraph of optionally styled and wrapped text.
//! - [`Scrollbar`]: displays a scrollbar.
//! - [`Sparkline`]: display a single data set as a sparkline.
//! - [`Table`]: displays multiple rows and columns in a grid and allows selection.
//! - [`Tabs`]: displays a tab bar and allows selection.
//!
//! [`Canvas`]: crate::widgets::canvas::Canvas
mod barchart;
pub mod block;
mod borders;
#[cfg(feature = "widget-calendar")]
pub mod calendar;
pub mod canvas;
mod chart;
mod clear;
mod gauge;
mod list;
mod logo;
mod paragraph;
mod reflow;
mod scrollbar;
mod sparkline;
mod table;
mod tabs;

pub use self::{
    barchart::{Bar, BarChart, BarGroup},
    block::{Block, BorderType, Padding},
    borders::*,
    chart::{Axis, Chart, Dataset, GraphType, LegendPosition},
    clear::Clear,
    gauge::{Gauge, LineGauge},
    list::{List, ListDirection, ListItem, ListState},
    logo::{RatatuiLogo, Size as RatatuiLogoSize},
    paragraph::{Paragraph, Wrap},
    scrollbar::{ScrollDirection, Scrollbar, ScrollbarOrientation, ScrollbarState},
    sparkline::{RenderDirection, Sparkline, SparklineBar},
    table::{Cell, HighlightSpacing, Row, Table, TableState},
    tabs::Tabs,
};
use crate::{buffer::Buffer, layout::Rect, style::Style};

/// A `Widget` is a type that can be drawn on a [`Buffer`] in a given [`Rect`].
///
/// Prior to Ratatui 0.26.0, widgets generally were created for each frame as they were consumed
/// during rendering. This meant that they were not meant to be stored but used as *commands* to
/// draw common figures in the UI.
///
/// Starting with Ratatui 0.26.0, all the internal widgets implement Widget for a reference to
/// themselves. This allows you to store a reference to a widget and render it later. Widget crates
/// should consider also doing this to allow for more flexibility in how widgets are used.
///
/// In Ratatui 0.26.0, we also added an unstable [`WidgetRef`] trait and implemented this on all the
/// internal widgets. In addition to the above benefit of rendering references to widgets, this also
/// allows you to render boxed widgets. This is useful when you want to store a collection of
/// widgets with different types. You can then iterate over the collection and render each widget.
/// See <https://github.com/ratatui/ratatui/issues/1287> for more information.
///
/// In general where you expect a widget to immutably work on its data, we recommended to implement
/// `Widget` for a reference to the widget (`impl Widget for &MyWidget`). If you need to store state
/// between draw calls, implement `StatefulWidget` if you want the Widget to be immutable, or
/// implement `Widget` for a mutable reference to the widget (`impl Widget for &mut MyWidget`) if
/// you want the widget to be mutable. The mutable widget pattern is used infrequently in apps, but
/// can be quite useful.
///
/// A blanket implementation of `Widget` for `&W` where `W` implements `WidgetRef` is provided.
/// Widget is also implemented for `&str` and `String` types.
///
/// # Examples
///
/// ```rust,no_run
/// use ratatui::{
///     backend::TestBackend,
///     widgets::{Clear, Widget},
///     Terminal,
/// };
/// # let backend = TestBackend::new(5, 5);
/// # let mut terminal = Terminal::new(backend).unwrap();
///
/// terminal.draw(|frame| {
///     frame.render_widget(Clear, frame.area());
/// });
/// ```
///
/// It's common to render widgets inside other widgets:
///
/// ```rust
/// use ratatui::{buffer::Buffer, layout::Rect, text::Line, widgets::Widget};
///
/// struct MyWidget;
///
/// impl Widget for MyWidget {
///     fn render(self, area: Rect, buf: &mut Buffer) {
///         Line::raw("Hello").render(area, buf);
///     }
/// }
/// ```
pub trait Widget {
    /// Draws the current state of the widget in the given buffer. That is the only method required
    /// to implement a custom widget.
    fn render(self, area: Rect, buf: &mut Buffer)
    where
        Self: Sized;
}

/// A `StatefulWidget` is a widget that can take advantage of some local state to remember things
/// between two draw calls.
///
/// Most widgets can be drawn directly based on the input parameters. However, some features may
/// require some kind of associated state to be implemented.
///
/// For example, the [`List`] widget can highlight the item currently selected. This can be
/// translated in an offset, which is the number of elements to skip in order to have the selected
/// item within the viewport currently allocated to this widget. The widget can therefore only
/// provide the following behavior: whenever the selected item is out of the viewport scroll to a
/// predefined position (making the selected item the last viewable item or the one in the middle
/// for example). Nonetheless, if the widget has access to the last computed offset then it can
/// implement a natural scrolling experience where the last offset is reused until the selected
/// item is out of the viewport.
///
/// ## Examples
///
/// ```rust,no_run
/// use std::io;
///
/// use ratatui::{
///     backend::TestBackend,
///     widgets::{List, ListItem, ListState, StatefulWidget, Widget},
///     Terminal,
/// };
///
/// // Let's say we have some events to display.
/// struct Events {
///     // `items` is the state managed by your application.
///     items: Vec<String>,
///     // `state` is the state that can be modified by the UI. It stores the index of the selected
///     // item as well as the offset computed during the previous draw call (used to implement
///     // natural scrolling).
///     state: ListState,
/// }
///
/// impl Events {
///     fn new(items: Vec<String>) -> Events {
///         Events {
///             items,
///             state: ListState::default(),
///         }
///     }
///
///     pub fn set_items(&mut self, items: Vec<String>) {
///         self.items = items;
///         // We reset the state as the associated items have changed. This effectively reset
///         // the selection as well as the stored offset.
///         self.state = ListState::default();
///     }
///
///     // Select the next item. This will not be reflected until the widget is drawn in the
///     // `Terminal::draw` callback using `Frame::render_stateful_widget`.
///     pub fn next(&mut self) {
///         let i = match self.state.selected() {
///             Some(i) => {
///                 if i >= self.items.len() - 1 {
///                     0
///                 } else {
///                     i + 1
///                 }
///             }
///             None => 0,
///         };
///         self.state.select(Some(i));
///     }
///
///     // Select the previous item. This will not be reflected until the widget is drawn in the
///     // `Terminal::draw` callback using `Frame::render_stateful_widget`.
///     pub fn previous(&mut self) {
///         let i = match self.state.selected() {
///             Some(i) => {
///                 if i == 0 {
///                     self.items.len() - 1
///                 } else {
///                     i - 1
///                 }
///             }
///             None => 0,
///         };
///         self.state.select(Some(i));
///     }
///
///     // Unselect the currently selected item if any. The implementation of `ListState` makes
///     // sure that the stored offset is also reset.
///     pub fn unselect(&mut self) {
///         self.state.select(None);
///     }
/// }
///
/// # let backend = TestBackend::new(5, 5);
/// # let mut terminal = Terminal::new(backend).unwrap();
///
/// let mut events = Events::new(vec![String::from("Item 1"), String::from("Item 2")]);
///
/// loop {
///     terminal.draw(|f| {
///         // The items managed by the application are transformed to something
///         // that is understood by ratatui.
///         let items: Vec<ListItem> = events
///             .items
///             .iter()
///             .map(|i| ListItem::new(i.as_str()))
///             .collect();
///         // The `List` widget is then built with those items.
///         let list = List::new(items);
///         // Finally the widget is rendered using the associated state. `events.state` is
///         // effectively the only thing that we will "remember" from this draw call.
///         f.render_stateful_widget(list, f.size(), &mut events.state);
///     });
///
///     // In response to some input events or an external http request or whatever:
///     events.next();
/// }
/// ```
pub trait StatefulWidget {
    /// State associated with the stateful widget.
    ///
    /// If you don't need this then you probably want to implement [`Widget`] instead.
    type State;
    /// Draws the current state of the widget in the given buffer. That is the only method required
    /// to implement a custom stateful widget.
    fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State);
}

/// A `WidgetRef` is a trait that allows rendering a widget by reference.
///
/// This trait is useful when you want to store a reference to a widget and render it later. It also
/// allows you to render boxed widgets.
///
/// Boxed widgets allow you to store widgets with a type that is not known at compile time. This is
/// useful when you want to store a collection of widgets with different types. You can then iterate
/// over the collection and render each widget.
///
/// This trait was introduced in Ratatui 0.26.0 and is implemented for all the internal widgets. It
/// is currently marked as unstable as we are still evaluating the API and may make changes in the
/// future. See <https://github.com/ratatui/ratatui/issues/1287> for more information.
///
/// A blanket implementation of `Widget` for `&W` where `W` implements `WidgetRef` is provided.
///
/// A blanket implementation of `WidgetRef` for `Option<W>` where `W` implements `WidgetRef` is
/// 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.
///
/// # Examples
///
/// ```rust
/// # #[cfg(feature = "unstable-widget-ref")] {
/// use ratatui::{
///     buffer::Buffer,
///     layout::Rect,
///     text::Line,
///     widgets::{Widget, WidgetRef},
/// };
///
/// struct Greeting;
///
/// struct Farewell;
///
/// impl WidgetRef for Greeting {
///     fn render_ref(&self, area: Rect, buf: &mut Buffer) {
///         Line::raw("Hello").render(area, buf);
///     }
/// }
///
/// /// Only needed for backwards compatibility
/// impl Widget for Greeting {
///     fn render(self, area: Rect, buf: &mut Buffer) {
///         self.render_ref(area, buf);
///     }
/// }
///
/// impl WidgetRef for Farewell {
///     fn render_ref(&self, area: Rect, buf: &mut Buffer) {
///         Line::raw("Goodbye").right_aligned().render(area, buf);
///     }
/// }
///
/// /// Only needed for backwards compatibility
/// impl Widget for Farewell {
///     fn render(self, area: Rect, buf: &mut Buffer) {
///         self.render_ref(area, buf);
///     }
/// }
///
/// # fn render(area: Rect, buf: &mut Buffer) {
/// let greeting = Greeting;
/// let farewell = Farewell;
///
/// // these calls do not consume the widgets, so they can be used again later
/// greeting.render_ref(area, buf);
/// farewell.render_ref(area, buf);
///
/// // a collection of widgets with different types
/// let widgets: Vec<Box<dyn WidgetRef>> = vec![Box::new(greeting), Box::new(farewell)];
/// for widget in widgets {
///     widget.render_ref(area, buf);
/// }
/// # }
/// # }
/// ```
#[instability::unstable(feature = "widget-ref")]
pub trait WidgetRef {
    /// Draws the current state of the widget in the given buffer. That is the only method required
    /// to implement a custom widget.
    fn render_ref(&self, area: Rect, buf: &mut Buffer);
}

/// This allows you to render a widget by reference.
impl<W: WidgetRef> Widget for &W {
    fn render(self, area: Rect, buf: &mut Buffer) {
        self.render_ref(area, buf);
    }
}

/// 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
/// widgets. It allows you to render an optional widget by reference.
///
/// The internal widgets use this pattern to render the optional `Block` widgets that are included
/// on most widgets.
/// Blanket implementation of `WidgetExt` for `Option<W>` where `W` implements `WidgetRef`.
///
/// # Examples
///
/// ```rust
/// # #[cfg(feature = "unstable-widget-ref")] {
/// use ratatui::{
///     buffer::Buffer,
///     layout::Rect,
///     text::Line,
///     widgets::{Widget, WidgetRef},
/// };
///
/// struct Parent {
///     child: Option<Child>,
/// }
///
/// struct Child;
///
/// impl WidgetRef for Child {
///     fn render_ref(&self, area: Rect, buf: &mut Buffer) {
///         Line::raw("Hello from child").render(area, buf);
///     }
/// }
///
/// impl WidgetRef for Parent {
///     fn render_ref(&self, area: Rect, buf: &mut Buffer) {
///         self.child.render_ref(area, buf);
///     }
/// }
/// # }
/// ```
impl<W: WidgetRef> WidgetRef for Option<W> {
    fn render_ref(&self, area: Rect, buf: &mut Buffer) {
        if let Some(widget) = self {
            widget.render_ref(area, buf);
        }
    }
}

/// A `StatefulWidgetRef` is a trait that allows rendering a stateful widget by reference.
///
/// This is the stateful equivalent of `WidgetRef`. It is useful when you want to store a reference
/// to a stateful widget and render it later. It also allows you to render boxed stateful widgets.
///
/// This trait was introduced in Ratatui 0.26.0 and is implemented for all the internal stateful
/// widgets. It is currently marked as unstable as we are still evaluating the API and may make
/// changes in the future. See <https://github.com/ratatui/ratatui/issues/1287> for more
/// information.
///
/// A blanket implementation of `StatefulWidget` for `&W` where `W` implements `StatefulWidgetRef`
/// is provided.
///
/// See the documentation for [`WidgetRef`] for more information on boxed widgets.
/// See the documentation for [`StatefulWidget`] for more information on stateful widgets.
///
/// # Examples
///
/// ```rust
/// # #[cfg(feature = "unstable-widget-ref")] {
/// use ratatui::{
///     buffer::Buffer,
///     layout::Rect,
///     style::Stylize,
///     text::Line,
///     widgets::{StatefulWidget, StatefulWidgetRef, Widget},
/// };
///
/// struct PersonalGreeting;
///
/// impl StatefulWidgetRef for PersonalGreeting {
///     type State = String;
///     fn render_ref(&self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
///         Line::raw(format!("Hello {}", state)).render(area, buf);
///     }
/// }
///
/// impl StatefulWidget for PersonalGreeting {
///     type State = String;
///     fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
///         (&self).render_ref(area, buf, state);
///     }
/// }
///
/// fn render(area: Rect, buf: &mut Buffer) {
///     let widget = PersonalGreeting;
///     let mut state = "world".to_string();
///     widget.render(area, buf, &mut state);
/// }
/// # }
/// ```
#[instability::unstable(feature = "widget-ref")]
pub trait StatefulWidgetRef {
    /// State associated with the stateful widget.
    ///
    /// If you don't need this then you probably want to implement [`WidgetRef`] instead.
    type State;
    /// Draws the current state of the widget in the given buffer. That is the only method required
    /// to implement a custom stateful widget.
    fn render_ref(&self, area: Rect, buf: &mut Buffer, state: &mut Self::State);
}

// Note: while StatefulWidgetRef is marked as unstable, the blanket implementation of StatefulWidget
// cannot be implemented as W::State is effectively pub(crate) and not accessible from outside the
// crate. Once stabilized, this blanket implementation can be added and the specific implementations
// on Table and List can be removed.
//
// /// Blanket implementation of `StatefulWidget` for `&W` where `W` implements `StatefulWidgetRef`.
// ///
// /// This allows you to render a stateful widget by reference.
// impl<W: StatefulWidgetRef> StatefulWidget for &W {
//     type State = W::State;
//     fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
//         StatefulWidgetRef::render_ref(self, area, buf, state);
//     }
// }

/// Renders a string slice as a widget.
///
/// This implementation allows a string slice (`&str`) to act as a widget, meaning it can be drawn
/// onto a [`Buffer`] in a specified [`Rect`]. The slice represents a static string which can be
/// rendered by reference, thereby avoiding the need for string cloning or ownership transfer when
/// drawing the text to the screen.
impl Widget for &str {
    fn render(self, area: Rect, buf: &mut Buffer) {
        self.render_ref(area, buf);
    }
}

/// Provides the ability to render a string slice by reference.
///
/// This trait implementation ensures that a string slice, which is an immutable view over a
/// `String`, can be drawn on demand without requiring ownership of the string itself. It utilizes
/// the default text style when rendering onto the provided [`Buffer`] at the position defined by
/// [`Rect`].
impl WidgetRef for &str {
    fn render_ref(&self, area: Rect, buf: &mut Buffer) {
        buf.set_stringn(area.x, area.y, self, area.width as usize, Style::new());
    }
}

/// Renders a `String` object as a widget.
///
/// This implementation enables an owned `String` to be treated as a widget, which can be rendered
/// on a [`Buffer`] within the bounds of a given [`Rect`].
impl Widget for String {
    fn render(self, area: Rect, buf: &mut Buffer) {
        self.render_ref(area, buf);
    }
}

/// Provides the ability to render a `String` by reference.
///
/// This trait allows for a `String` to be rendered onto the [`Buffer`], similarly using the default
/// style settings. It ensures that an owned `String` can be rendered efficiently by reference,
/// without the need to give up ownership of the underlying text.
impl WidgetRef for String {
    fn render_ref(&self, area: Rect, buf: &mut Buffer) {
        buf.set_stringn(area.x, area.y, self, area.width as usize, Style::new());
    }
}

#[cfg(test)]
mod tests {
    use rstest::{fixture, rstest};

    use super::*;
    use crate::text::Line;

    #[fixture]
    fn buf() -> Buffer {
        Buffer::empty(Rect::new(0, 0, 20, 1))
    }

    mod widget {
        use super::*;

        struct Greeting;

        impl Widget for Greeting {
            fn render(self, area: Rect, buf: &mut Buffer) {
                Line::from("Hello").render(area, buf);
            }
        }

        #[rstest]
        fn render(mut buf: Buffer) {
            let widget = Greeting;
            widget.render(buf.area, &mut buf);
            assert_eq!(buf, Buffer::with_lines(["Hello               "]));
        }
    }

    mod widget_ref {
        use super::*;

        struct Greeting;
        struct Farewell;

        impl WidgetRef for Greeting {
            fn render_ref(&self, area: Rect, buf: &mut Buffer) {
                Line::from("Hello").render(area, buf);
            }
        }

        impl WidgetRef for Farewell {
            fn render_ref(&self, area: Rect, buf: &mut Buffer) {
                Line::from("Goodbye").right_aligned().render(area, buf);
            }
        }

        #[rstest]
        fn render_ref(mut buf: Buffer) {
            let widget = Greeting;
            widget.render_ref(buf.area, &mut buf);
            assert_eq!(buf, Buffer::with_lines(["Hello               "]));
        }

        /// Ensure that the blanket implementation of `Widget` for `&W` where `W` implements
        /// `WidgetRef` works as expected.
        #[rstest]
        fn blanket_render(mut buf: Buffer) {
            let widget = &Greeting;
            widget.render(buf.area, &mut buf);
            assert_eq!(buf, Buffer::with_lines(["Hello               "]));
        }

        #[rstest]
        fn box_render_ref(mut buf: Buffer) {
            let widget: Box<dyn WidgetRef> = Box::new(Greeting);
            widget.render_ref(buf.area, &mut buf);
            assert_eq!(buf, Buffer::with_lines(["Hello               "]));
        }

        #[rstest]
        fn vec_box_render(mut buf: Buffer) {
            let widgets: Vec<Box<dyn WidgetRef>> = vec![Box::new(Greeting), Box::new(Farewell)];
            for widget in widgets {
                widget.render_ref(buf.area, &mut buf);
            }
            assert_eq!(buf, Buffer::with_lines(["Hello        Goodbye"]));
        }
    }

    #[fixture]
    fn state() -> String {
        "world".to_string()
    }

    mod stateful_widget {
        use super::*;

        struct PersonalGreeting;

        impl StatefulWidget for PersonalGreeting {
            type State = String;
            fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
                Line::from(format!("Hello {state}")).render(area, buf);
            }
        }

        #[rstest]
        fn render(mut buf: Buffer, mut state: String) {
            let widget = PersonalGreeting;
            widget.render(buf.area, &mut buf, &mut state);
            assert_eq!(buf, Buffer::with_lines(["Hello world         "]));
        }
    }

    mod stateful_widget_ref {
        use super::*;

        struct PersonalGreeting;

        impl StatefulWidgetRef for PersonalGreeting {
            type State = String;
            fn render_ref(&self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
                Line::from(format!("Hello {state}")).render(area, buf);
            }
        }

        #[rstest]
        fn render_ref(mut buf: Buffer, mut state: String) {
            let widget = PersonalGreeting;
            widget.render_ref(buf.area, &mut buf, &mut state);
            assert_eq!(buf, Buffer::with_lines(["Hello world         "]));
        }

        // Note this cannot be tested until the blanket implementation of StatefulWidget for &W
        // where W implements StatefulWidgetRef is added. (see the comment in the blanket
        // implementation for more).
        // /// This test is to ensure that the blanket implementation of `StatefulWidget` for `&W`
        // where /// `W` implements `StatefulWidgetRef` works as expected.
        // #[rstest]
        // fn stateful_widget_blanket_render(mut buf: Buffer, mut state: String) {
        //     let widget = &PersonalGreeting;
        //     widget.render(buf.area, &mut buf, &mut state);
        //     assert_eq!(buf, Buffer::with_lines(["Hello world         "]));
        // }

        #[rstest]
        fn box_render_render(mut buf: Buffer, mut state: String) {
            let widget = Box::new(PersonalGreeting);
            widget.render_ref(buf.area, &mut buf, &mut state);
            assert_eq!(buf, Buffer::with_lines(["Hello world         "]));
        }
    }

    mod option_widget_ref {
        use super::*;

        struct Greeting;

        impl WidgetRef for Greeting {
            fn render_ref(&self, area: Rect, buf: &mut Buffer) {
                Line::from("Hello").render(area, buf);
            }
        }

        #[rstest]
        fn render_ref_some(mut buf: Buffer) {
            let widget = Some(Greeting);
            widget.render_ref(buf.area, &mut buf);
            assert_eq!(buf, Buffer::with_lines(["Hello               "]));
        }

        #[rstest]
        fn render_ref_none(mut buf: Buffer) {
            let widget: Option<Greeting> = None;
            widget.render_ref(buf.area, &mut buf);
            assert_eq!(buf, Buffer::with_lines(["                    "]));
        }
    }

    mod str {
        use super::*;

        #[rstest]
        fn render(mut buf: Buffer) {
            "hello world".render(buf.area, &mut buf);
            assert_eq!(buf, Buffer::with_lines(["hello world         "]));
        }

        #[rstest]
        fn render_area(mut buf: Buffer) {
            let area = Rect::new(buf.area.x, buf.area.y, 11, buf.area.height);
            "hello world, just hello".render(area, &mut buf);
            assert_eq!(buf, Buffer::with_lines(["hello world         "]));
        }

        #[rstest]
        fn render_ref(mut buf: Buffer) {
            "hello world".render_ref(buf.area, &mut buf);
            assert_eq!(buf, Buffer::with_lines(["hello world         "]));
        }

        #[rstest]
        fn option_render(mut buf: Buffer) {
            Some("hello world").render(buf.area, &mut buf);
            assert_eq!(buf, Buffer::with_lines(["hello world         "]));
        }

        #[rstest]
        fn option_render_ref(mut buf: Buffer) {
            Some("hello world").render_ref(buf.area, &mut buf);
            assert_eq!(buf, Buffer::with_lines(["hello world         "]));
        }
    }

    mod string {
        use super::*;
        #[rstest]
        fn render(mut buf: Buffer) {
            String::from("hello world").render(buf.area, &mut buf);
            assert_eq!(buf, Buffer::with_lines(["hello world         "]));
        }

        #[rstest]
        fn render_area(mut buf: Buffer) {
            let area = Rect::new(buf.area.x, buf.area.y, 11, buf.area.height);
            String::from("hello world, just hello").render(area, &mut buf);
            assert_eq!(buf, Buffer::with_lines(["hello world         "]));
        }

        #[rstest]
        fn render_ref(mut buf: Buffer) {
            String::from("hello world").render_ref(buf.area, &mut buf);
            assert_eq!(buf, Buffer::with_lines(["hello world         "]));
        }

        #[rstest]
        fn option_render(mut buf: Buffer) {
            Some(String::from("hello world")).render(buf.area, &mut buf);
            assert_eq!(buf, Buffer::with_lines(["hello world         "]));
        }

        #[rstest]
        fn option_render_ref(mut buf: Buffer) {
            Some(String::from("hello world")).render_ref(buf.area, &mut buf);
            assert_eq!(buf, Buffer::with_lines(["hello world         "]));
        }
    }
}