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}