1 //! `widgets` is a collection of types that implement [`Widget`] or [`StatefulWidget`] or both. 2 //! 3 //! All widgets are implemented using the builder pattern and are consumable objects. They are not 4 //! meant to be stored but used as *commands* to draw common figures in the UI. 5 //! 6 //! The available widgets are: 7 //! - [`Block`] 8 //! - [`Tabs`] 9 //! - [`List`] 10 //! - [`Table`] 11 //! - [`Paragraph`] 12 //! - [`Chart`] 13 //! - [`BarChart`] 14 //! - [`Gauge`] 15 //! - [`Sparkline`] 16 //! - [`Clear`] 17 18 mod barchart; 19 mod block; 20 pub mod canvas; 21 mod chart; 22 mod clear; 23 mod gauge; 24 mod list; 25 mod paragraph; 26 mod reflow; 27 mod sparkline; 28 mod table; 29 mod tabs; 30 31 pub use self::barchart::BarChart; 32 pub use self::block::{Block, BorderType}; 33 pub use self::chart::{Axis, Chart, Dataset, GraphType}; 34 pub use self::clear::Clear; 35 pub use self::gauge::{Gauge, LineGauge}; 36 pub use self::list::{List, ListItem, ListState}; 37 pub use self::paragraph::{Paragraph, Wrap}; 38 pub use self::sparkline::Sparkline; 39 pub use self::table::{Cell, Row, Table, TableState}; 40 pub use self::tabs::Tabs; 41 42 use crate::{buffer::Buffer, layout::Rect}; 43 use bitflags::bitflags; 44 45 bitflags! { 46 /// Bitflags that can be composed to set the visible borders essentially on the block widget. 47 pub struct Borders: u32 { 48 /// Show no border (default) 49 const NONE = 0b0000_0001; 50 /// Show the top border 51 const TOP = 0b0000_0010; 52 /// Show the right border 53 const RIGHT = 0b0000_0100; 54 /// Show the bottom border 55 const BOTTOM = 0b000_1000; 56 /// Show the left border 57 const LEFT = 0b0001_0000; 58 /// Show all borders 59 const ALL = Self::TOP.bits | Self::RIGHT.bits | Self::BOTTOM.bits | Self::LEFT.bits; 60 } 61 } 62 63 /// Base requirements for a Widget 64 pub trait Widget { 65 /// Draws the current state of the widget in the given buffer. That the only method required to 66 /// implement a custom widget. render(self, area: Rect, buf: &mut Buffer)67 fn render(self, area: Rect, buf: &mut Buffer); 68 } 69 70 /// A `StatefulWidget` is a widget that can take advantage of some local state to remember things 71 /// between two draw calls. 72 /// 73 /// Most widgets can be drawn directly based on the input parameters. However, some features may 74 /// require some kind of associated state to be implemented. 75 /// 76 /// For example, the [`List`] widget can highlight the item currently selected. This can be 77 /// translated in an offset, which is the number of elements to skip in order to have the selected 78 /// item within the viewport currently allocated to this widget. The widget can therefore only 79 /// provide the following behavior: whenever the selected item is out of the viewport scroll to a 80 /// predefined position (making the selected item the last viewable item or the one in the middle 81 /// for example). Nonetheless, if the widget has access to the last computed offset then it can 82 /// implement a natural scrolling experience where the last offset is reused until the selected 83 /// item is out of the viewport. 84 /// 85 /// ## Examples 86 /// 87 /// ```rust,no_run 88 /// # use std::io; 89 /// # use tui::Terminal; 90 /// # use tui::backend::{Backend, TermionBackend}; 91 /// # use tui::widgets::{Widget, List, ListItem, ListState}; 92 /// 93 /// // Let's say we have some events to display. 94 /// struct Events { 95 /// // `items` is the state managed by your application. 96 /// items: Vec<String>, 97 /// // `state` is the state that can be modified by the UI. It stores the index of the selected 98 /// // item as well as the offset computed during the previous draw call (used to implement 99 /// // natural scrolling). 100 /// state: ListState 101 /// } 102 /// 103 /// impl Events { 104 /// fn new(items: Vec<String>) -> Events { 105 /// Events { 106 /// items, 107 /// state: ListState::default(), 108 /// } 109 /// } 110 /// 111 /// pub fn set_items(&mut self, items: Vec<String>) { 112 /// self.items = items; 113 /// // We reset the state as the associated items have changed. This effectively reset 114 /// // the selection as well as the stored offset. 115 /// self.state = ListState::default(); 116 /// } 117 /// 118 /// // Select the next item. This will not be reflected until the widget is drawn in the 119 /// // `Terminal::draw` callback using `Frame::render_stateful_widget`. 120 /// pub fn next(&mut self) { 121 /// let i = match self.state.selected() { 122 /// Some(i) => { 123 /// if i >= self.items.len() - 1 { 124 /// 0 125 /// } else { 126 /// i + 1 127 /// } 128 /// } 129 /// None => 0, 130 /// }; 131 /// self.state.select(Some(i)); 132 /// } 133 /// 134 /// // Select the previous item. This will not be reflected until the widget is drawn in the 135 /// // `Terminal::draw` callback using `Frame::render_stateful_widget`. 136 /// pub fn previous(&mut self) { 137 /// let i = match self.state.selected() { 138 /// Some(i) => { 139 /// if i == 0 { 140 /// self.items.len() - 1 141 /// } else { 142 /// i - 1 143 /// } 144 /// } 145 /// None => 0, 146 /// }; 147 /// self.state.select(Some(i)); 148 /// } 149 /// 150 /// // Unselect the currently selected item if any. The implementation of `ListState` makes 151 /// // sure that the stored offset is also reset. 152 /// pub fn unselect(&mut self) { 153 /// self.state.select(None); 154 /// } 155 /// } 156 /// 157 /// let stdout = io::stdout(); 158 /// let backend = TermionBackend::new(stdout); 159 /// let mut terminal = Terminal::new(backend).unwrap(); 160 /// 161 /// let mut events = Events::new(vec![ 162 /// String::from("Item 1"), 163 /// String::from("Item 2") 164 /// ]); 165 /// 166 /// loop { 167 /// terminal.draw(|f| { 168 /// // The items managed by the application are transformed to something 169 /// // that is understood by tui. 170 /// let items: Vec<ListItem>= events.items.iter().map(|i| ListItem::new(i.as_ref())).collect(); 171 /// // The `List` widget is then built with those items. 172 /// let list = List::new(items); 173 /// // Finally the widget is rendered using the associated state. `events.state` is 174 /// // effectively the only thing that we will "remember" from this draw call. 175 /// f.render_stateful_widget(list, f.size(), &mut events.state); 176 /// }); 177 /// 178 /// // In response to some input events or an external http request or whatever: 179 /// events.next(); 180 /// } 181 /// ``` 182 pub trait StatefulWidget { 183 type State; render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State)184 fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State); 185 } 186