From bcd1e303768e0d642eabfabe2b4c68dcafc43cd3 Mon Sep 17 00:00:00 2001 From: Florian Dehau Date: Tue, 4 Sep 2018 21:45:03 +0200 Subject: [PATCH] refactor: update List select behavior * allow a selectable list to have no selected item * show highlight_symbol only when something is selected --- examples/demo.rs | 2 +- examples/list.rs | 37 ++++++++++++++++++++++++++----------- src/widgets/list.rs | 28 ++++++++++++++++++---------- 3 files changed, 45 insertions(+), 22 deletions(-) diff --git a/examples/demo.rs b/examples/demo.rs index 77616080..ca7565b4 100644 --- a/examples/demo.rs +++ b/examples/demo.rs @@ -355,7 +355,7 @@ fn draw_charts(f: &mut Frame, app: &App, area: Rect) { SelectableList::default() .block(Block::default().borders(Borders::ALL).title("List")) .items(&app.items) - .select(app.selected) + .select(Some(app.selected)) .highlight_style(Style::default().fg(Color::Yellow).modifier(Modifier::Bold)) .highlight_symbol(">") .render(f, chunks[0]); diff --git a/examples/list.rs b/examples/list.rs index c8e62847..db461dce 100644 --- a/examples/list.rs +++ b/examples/list.rs @@ -18,7 +18,7 @@ use tui::Terminal; struct App<'a> { size: Rect, items: Vec<&'a str>, - selected: usize, + selected: Option, events: Vec<(&'a str, &'a str)>, info_style: Style, warning_style: Style, @@ -35,7 +35,7 @@ impl<'a> App<'a> { "Item10", "Item11", "Item12", "Item13", "Item14", "Item15", "Item16", "Item17", "Item18", "Item19", "Item20", "Item21", "Item22", "Item23", "Item24", ], - selected: 0, + selected: None, events: vec![ ("Event1", "INFO"), ("Event2", "INFO"), @@ -132,17 +132,31 @@ fn main() { event::Key::Char('q') => { break; } + event::Key::Left => { + app.selected = None; + } event::Key::Down => { - app.selected += 1; - if app.selected > app.items.len() - 1 { - app.selected = 0; + app.selected = if let Some(selected) = app.selected { + if selected >= app.items.len() - 1 { + Some(0) + } else { + Some(selected + 1) + } + } else { + Some(0) + } + } + event::Key::Up => { + app.selected = if let Some(selected) = app.selected { + if selected > 0 { + Some(selected - 1) + } else { + Some(app.items.len() - 1) + } + } else { + Some(0) } } - event::Key::Up => if app.selected > 0 { - app.selected -= 1; - } else { - app.selected = app.items.len() - 1; - }, _ => {} }, Event::Tick => { @@ -153,6 +167,7 @@ fn main() { } terminal.show_cursor().unwrap(); + terminal.clear().unwrap(); } fn draw(t: &mut Terminal, app: &App) -> Result<(), io::Error> { @@ -181,7 +196,7 @@ fn draw(t: &mut Terminal, app: &App) -> Result<(), io::Error> { "WARNING" => &app.warning_style, _ => &app.info_style, }, - ) + ) }); List::new(events) .block(Block::default().borders(Borders::ALL).title("List")) diff --git a/src/widgets/list.rs b/src/widgets/list.rs index d8dbf49a..53f36d45 100644 --- a/src/widgets/list.rs +++ b/src/widgets/list.rs @@ -137,7 +137,7 @@ where /// SelectableList::default() /// .block(Block::default().title("SelectableList").borders(Borders::ALL)) /// .items(&["Item 1", "Item 2", "Item 3"]) -/// .select(1) +/// .select(Some(1)) /// .style(Style::default().fg(Color::White)) /// .highlight_style(Style::default().modifier(Modifier::Italic)) /// .highlight_symbol(">>"); @@ -199,8 +199,8 @@ impl<'b> SelectableList<'b> { self } - pub fn select(mut self, index: usize) -> SelectableList<'b> { - self.selected = Some(index); + pub fn select(mut self, index: Option) -> SelectableList<'b> { + self.selected = index; self } } @@ -216,16 +216,20 @@ impl<'b> Widget for SelectableList<'b> { // Use highlight_style only if something is selected let (selected, highlight_style) = match self.selected { - Some(i) => (i, &self.highlight_style), - None => (0, &self.style), + Some(i) => (Some(i), &self.highlight_style), + None => (None, &self.style), }; let highlight_symbol = self.highlight_symbol.unwrap_or(""); let blank_symbol = iter::repeat(" ") .take(highlight_symbol.width()) .collect::(); // Make sure the list show the selected item - let offset = if selected >= list_height { - selected - list_height + 1 + let offset = if let Some(selected) = selected { + if selected >= list_height { + selected - list_height + 1 + } else { + 0 + } } else { 0 }; @@ -236,10 +240,14 @@ impl<'b> Widget for SelectableList<'b> { .iter() .enumerate() .map(|(i, item)| { - if i == selected { - Item::StyledData(format!("{} {}", highlight_symbol, item), highlight_style) + if let Some(s) = selected { + if i == s { + Item::StyledData(format!("{} {}", highlight_symbol, item), highlight_style) + } else { + Item::StyledData(format!("{} {}", blank_symbol, item), &self.style) + } } else { - Item::StyledData(format!("{} {}", blank_symbol, item), &self.style) + Item::StyledData(format!("{}", item), &self.style) } }) .skip(offset as usize);