diff --git a/examples/prototype.rs b/examples/prototype.rs index c9660dc..6a4e682 100644 --- a/examples/prototype.rs +++ b/examples/prototype.rs @@ -72,9 +72,10 @@ impl Iterator for SinSignal { } } -struct App { +struct App<'a> { name: String, - items: Vec, + items: Vec<&'a str>, + items2: Vec<&'a str>, selected: usize, show_chart: bool, progress: u16, @@ -112,7 +113,11 @@ fn main() { let mut app = App { name: String::from("Test app"), - items: ["1", "2", "3"].into_iter().map(|e| String::from(*e)).collect(), + items: vec!["Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", + "Item9", "Item10"], + items2: vec!["Event1", "Event2", "Event3", "Event4", "Event5", "Event6", "Event7", + "Event8", "Event9", "Event10", "Event11", "Event12", "Event13", "Event14", + "Event15", "Event16", "Event17"], selected: 0, show_chart: true, progress: 0, @@ -197,6 +202,8 @@ fn main() { if app.selected >= app.items.len() { app.selected = 0; } + let i = app.items2.pop().unwrap(); + app.items2.insert(0, i); app.color_index += 1; if app.color_index >= app.colors.len() { app.color_index = 0; @@ -214,7 +221,7 @@ fn draw(t: &mut Terminal, app: &App) { Group::default() .direction(Direction::Vertical) .alignment(Alignment::Left) - .chunks(&[Size::Fixed(7), Size::Min(5), Size::Fixed(3)]) + .chunks(&[Size::Fixed(7), Size::Min(5), Size::Fixed(5)]) .render(t, &size, |t, chunks| { Block::default().borders(border::ALL).title("Graphs").render(&chunks[0], t); Group::default() @@ -244,9 +251,27 @@ fn draw(t: &mut Terminal, app: &App) { .alignment(Alignment::Left) .chunks(&sizes) .render(t, &chunks[1], |t, chunks| { - List::default() - .block(Block::default().borders(border::ALL).title("List")) - .render(&chunks[0], t); + Group::default() + .direction(Direction::Vertical) + .chunks(&[Size::Min(20), Size::Max(40)]) + .render(t, &chunks[0], |t, chunks| { + Group::default() + .direction(Direction::Horizontal) + .chunks(&[Size::Max(20), Size::Min(0)]) + .render(t, &chunks[0], |t, chunks| { + List::default() + .block(Block::default().borders(border::ALL).title("List")) + .items(&app.items) + .select(app.selected) + .selection_color(Color::LightYellow) + .selection_symbol(">") + .render(&chunks[0], t); + List::default() + .block(Block::default().borders(border::ALL).title("List")) + .items(&app.items2) + .render(&chunks[1], t); + }) + }); if app.show_chart { Chart::default() .block(Block::default().title("Chart")) diff --git a/src/widgets/list.rs b/src/widgets/list.rs index 55af651..0b14151 100644 --- a/src/widgets/list.rs +++ b/src/widgets/list.rs @@ -1,5 +1,7 @@ use std::cmp::min; +use unicode_width::UnicodeWidthStr; + use buffer::Buffer; use widgets::{Widget, Block}; use layout::Rect; @@ -8,7 +10,11 @@ use style::Color; pub struct List<'a> { block: Option>, selected: usize, - items: Vec<(&'a str, Color, Color)>, + selection_symbol: Option<&'a str>, + selection_color: Color, + text_color: Color, + bg: Color, + items: &'a [&'a str], } impl<'a> Default for List<'a> { @@ -16,7 +22,11 @@ impl<'a> Default for List<'a> { List { block: None, selected: 0, - items: Vec::new(), + selection_symbol: None, + selection_color: Color::Reset, + text_color: Color::Reset, + bg: Color::Reset, + items: &[], } } } @@ -27,15 +37,39 @@ impl<'a> List<'a> { self } - pub fn items(&'a mut self, items: &[(&'a str, Color, Color)]) -> &mut List<'a> { - self.items = items.to_vec(); + pub fn items(&'a mut self, items: &'a [&'a str]) -> &mut List<'a> { + self.items = items; + self + } + + pub fn text_color(&'a mut self, text_color: Color) -> &mut List<'a> { + self.text_color = text_color; + self + } + + pub fn bg(&'a mut self, bg: Color) -> &mut List<'a> { + self.bg = bg; + self + } + + pub fn selection_symbol(&'a mut self, selection_symbol: &'a str) -> &mut List<'a> { + self.selection_symbol = Some(selection_symbol); + self + } + + pub fn selection_color(&'a mut self, selection_color: Color) -> &mut List<'a> { + self.selection_color = selection_color; + self + } + + pub fn select(&'a mut self, index: usize) -> &'a mut List<'a> { + self.selected = index; self } } impl<'a> Widget<'a> for List<'a> { fn buffer(&'a self, area: &Rect) -> Buffer<'a> { - let (mut buf, list_area) = match self.block { Some(ref b) => (b.buffer(area), b.inner(*area)), None => (Buffer::empty(*area), *area), @@ -49,10 +83,26 @@ impl<'a> Widget<'a> for List<'a> { } else { 0 }; + let x = match self.selection_symbol { + Some(s) => (s.width() + 2) as u16, + None => 1, + }; for i in 0..bound { let index = i + offset; - let (item, fg, bg) = self.items[index]; - buf.set_string(1, 1 + i as u16, item, fg, bg); + let item = self.items[index]; + let color = if index == self.selected { + self.selection_color + } else { + self.text_color + }; + buf.set_string(x, 1 + i as u16, item, color, self.bg); + } + if let Some(s) = self.selection_symbol { + buf.set_string(1, + (1 + self.selected - offset) as u16, + s, + self.selection_color, + self.bg); } buf }