[][src]Trait tui::widgets::StatefulWidget

pub trait StatefulWidget {
    type State;
    fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State);
}

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


// 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 stdout = io::stdout();
let backend = TermionBackend::new(stdout);
let mut terminal = Terminal::new(backend).unwrap();

let mut events = Events::new(vec![
    String::from("Item 1"),
    String::from("Item 2")
]);

loop {
    terminal.draw(|mut f| {
        // The items managed by the application are transformed to something
        // that is understood by tui.
        let items = events.items.iter().map(Text::raw);
        // 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();
}

Associated Types

type State

Loading content...

Required methods

fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State)

Loading content...

Implementors

impl<'a, H, D, R> StatefulWidget for Table<'a, H, R> where
    H: Iterator,
    H::Item: Display,
    D: Iterator,
    D::Item: Display,
    R: Iterator<Item = Row<D>>, 
[src]

type State = TableState

impl<'b, L> StatefulWidget for List<'b, L> where
    L: Iterator<Item = Text<'b>>, 
[src]

type State = ListState

Loading content...