diff --git a/examples/select.rs b/examples/select.rs index 1f2c735..c398348 100644 --- a/examples/select.rs +++ b/examples/select.rs @@ -4,7 +4,7 @@ use std::fs::File; use std::io::{BufReader,BufRead}; use cursive::Cursive; -use cursive::view::{Dialog,SelectView,TextView,Selector,BoxView}; +use cursive::view::{Dialog,SelectView,TextView,BoxView}; fn main() { // To keep things simple, little error management is done here. @@ -22,17 +22,15 @@ fn main() { let mut siv = Cursive::new(); // Let's add a BoxView to keep the list at a reasonable size - it can scroll anyway. - siv.add_layer(Dialog::new(BoxView::new((20,10), select.with_id("city"))) - .title("Where are you from?") - .button("Ok", |s| { - // Find the SelectView, gets its selection. - let city = s.find::(&Selector::Id("city")).unwrap().selection().to_string(); - // And show the next window. - s.pop_layer(); - s.add_layer(Dialog::new(TextView::new(&format!("{} is a great city!", city))) - .button("Quit", |s| s.quit())); - })); + siv.add_layer(Dialog::new(BoxView::new((20,10), select.on_select(|s,city| show_next_window(s,city)))) + .title("Where are you from?")); siv.run(); } +// Let's put the callback in a separate function to keep it clean, but it's not required. +fn show_next_window(siv: &mut Cursive, city: &str) { + siv.pop_layer(); + siv.add_layer(Dialog::new(TextView::new(&format!("{} is a great city!", city))) + .button("Quit", |s| s.quit())); +} diff --git a/src/view/select_view.rs b/src/view/select_view.rs index 40e16ec..7ef297b 100644 --- a/src/view/select_view.rs +++ b/src/view/select_view.rs @@ -1,6 +1,8 @@ use std::cmp::min; +use std::rc::Rc; use color; +use ::Cursive; use view::{View,IdView,SizeRequest,DimensionRequest}; use event::{Event,EventResult,Key}; use vec::Vec2; @@ -9,14 +11,14 @@ use super::scroll::ScrollBase; struct Item { label: String, - value: T, + value: Rc, } impl Item { fn new(label: &str, value: T) -> Self { Item { label: label.to_string(), - value: value, + value: Rc::new(value), } } } @@ -28,21 +30,32 @@ pub struct SelectView { items: Vec>, focus: usize, scrollbase: ScrollBase, + select_cb: Option>>, } -impl SelectView { +impl SelectView { /// Creates a new empty SelectView. pub fn new() -> Self { SelectView { items: Vec::new(), focus: 0, scrollbase: ScrollBase::new(), + select_cb: None, } } + /// Sets a function to be called when an item is selected (when ENTER is pressed). + pub fn on_select(mut self, cb: F) -> Self + where F: Fn(&mut Cursive,&T) + 'static + { + self.select_cb = Some(Rc::new(Box::new(cb))); + + self + } + /// Returns the value of the currently selected item. Panics if the list is empty. - pub fn selection(&self) -> &T { - &self.items[self.focus].value + pub fn selection(&self) -> Rc { + self.items[self.focus].value.clone() } /// Adds a item to the list, with given label and value. @@ -76,7 +89,7 @@ impl SelectView { } -impl View for SelectView { +impl View for SelectView { fn draw(&mut self, printer: &Printer) { self.scrollbase.draw(printer, |printer,i| { @@ -115,6 +128,13 @@ impl View for SelectView { Event::KeyEvent(Key::PageDown) => self.focus = min(self.focus+10,self.items.len()-1), Event::KeyEvent(Key::Home) => self.focus = 0, Event::KeyEvent(Key::End) => self.focus = self.items.len()-1, + Event::KeyEvent(Key::Enter) if self.select_cb.is_some() => { + if let Some(ref cb) = self.select_cb { + let cb = cb.clone(); + let v = self.selection(); + return EventResult::Consumed(Some(Rc::new(Box::new(move |s| cb(s, &*v))))); + } + }, Event::CharEvent(c) => { // Starting from the current focus, find the first item that match the char. // Cycle back to the beginning of the list when we reach the end.