Add on_select to SelectView

And renamed existing `on_select` to `on_submit`
This commit is contained in:
Alexandre Bury 2016-07-30 01:27:34 -07:00
parent 2e05a0825a
commit 1165e70e15

View File

@ -32,7 +32,7 @@ use unicode_width::UnicodeWidthStr;
/// time_select.add_item("Medium", 5); /// time_select.add_item("Medium", 5);
/// time_select.add_item("Long", 10); /// time_select.add_item("Long", 10);
/// ///
/// time_select.set_on_select(|s, time| { /// time_select.set_on_submit(|s, time| {
/// s.pop_layer(); /// s.pop_layer();
/// let text = format!("You will wait for {} minutes...", time); /// let text = format!("You will wait for {} minutes...", time);
/// s.add_layer(Dialog::new(TextView::new(&text)) /// s.add_layer(Dialog::new(TextView::new(&text))
@ -51,8 +51,11 @@ pub struct SelectView<T = String> {
// the focus needs to be manipulable from callbacks // the focus needs to be manipulable from callbacks
focus: Rc<Cell<usize>>, focus: Rc<Cell<usize>>,
scrollbase: ScrollBase, scrollbase: ScrollBase,
// This is a custom callback to include a &T // This is a custom callback to include a &T.
select_cb: Option<Rc<Fn(&mut Cursive, &T)>>, // It will be called whenever "Enter" is pressed.
on_submit: Option<Rc<Fn(&mut Cursive, &T)>>,
// This callback is called when the selection is changed.
on_select: Option<Rc<Fn(&mut Cursive, &T)>>,
align: Align, align: Align,
// `true` if we show a one-line view, with popup on selection. // `true` if we show a one-line view, with popup on selection.
popup: bool, popup: bool,
@ -70,7 +73,8 @@ impl<T: 'static> SelectView<T> {
enabled: true, enabled: true,
focus: Rc::new(Cell::new(0)), focus: Rc::new(Cell::new(0)),
scrollbase: ScrollBase::new(), scrollbase: ScrollBase::new(),
select_cb: None, on_select: None,
on_submit: None,
align: Align::top_left(), align: Align::top_left(),
popup: false, popup: false,
last_offset: Cell::new(Vec2::zero()), last_offset: Cell::new(Vec2::zero()),
@ -120,27 +124,43 @@ impl<T: 'static> SelectView<T> {
} }
/// Sets a callback to be used when an item is selected. /// Sets a callback to be used when an item is selected.
///
/// (When ENTER is pressed on an item).
pub fn set_on_select<F>(&mut self, cb: F) pub fn set_on_select<F>(&mut self, cb: F)
where F: Fn(&mut Cursive, &T) + 'static where F: Fn(&mut Cursive, &T) + 'static
{ {
self.select_cb = Some(Rc::new(cb)); self.on_select = Some(Rc::new(cb));
} }
/// Sets a callback to be used when an item is selected. /// Sets a callback to be used when an item is selected.
/// ///
/// (When ENTER is pressed on an item).
/// ///
/// Chainable variant. /// Chainable variant.
pub fn on_select<F>(mut self, cb: F) -> Self pub fn on_select<F>(self, cb: F) -> Self
where F: Fn(&mut Cursive, &T) + 'static where F: Fn(&mut Cursive, &T) + 'static
{ {
self.set_on_select(cb); self.with(|s| s.set_on_select(cb))
self
} }
/// Sets a callback to be used when `<Enter>` is pressed.
///
/// The item currently selected will be given to the callback.
pub fn set_on_submit<F>(&mut self, cb: F)
where F: Fn(&mut Cursive, &T) + 'static
{
self.on_submit = Some(Rc::new(cb));
}
/// Sets a callback to be used when `<Enter>` is pressed.
///
/// The item currently selected will be given to the callback.
///
/// Chainable variant.
pub fn on_submit<F>(self, cb: F) -> Self
where F: Fn(&mut Cursive, &T) + 'static
{
self.with(|s| s.set_on_submit(cb))
}
/// Sets the alignment for this view. /// Sets the alignment for this view.
pub fn align(mut self, align: Align) -> Self { pub fn align(mut self, align: Align) -> Self {
self.align = align; self.align = align;
@ -311,12 +331,12 @@ impl<T: 'static> View for SelectView<T> {
let mut tree = MenuTree::new(); let mut tree = MenuTree::new();
for (i, item) in self.items.iter().enumerate() { for (i, item) in self.items.iter().enumerate() {
let focus = self.focus.clone(); let focus = self.focus.clone();
let select_cb = self.select_cb.as_ref().cloned(); let on_submit = self.on_submit.as_ref().cloned();
let value = item.value.clone(); let value = item.value.clone();
tree.add_leaf(&item.label, move |s| { tree.add_leaf(&item.label, move |s| {
focus.set(i); focus.set(i);
if let Some(ref select_cb) = select_cb { if let Some(ref on_submit) = on_submit {
select_cb(s, &value); on_submit(s, &value);
} }
}); });
} }
@ -367,12 +387,12 @@ impl<T: 'static> View for SelectView<T> {
Event::Key(Key::PageDown) => self.focus_down(10), Event::Key(Key::PageDown) => self.focus_down(10),
Event::Key(Key::Home) => self.focus.set(0), Event::Key(Key::Home) => self.focus.set(0),
Event::Key(Key::End) => self.focus.set(self.items.len() - 1), Event::Key(Key::End) => self.focus.set(self.items.len() - 1),
Event::Key(Key::Enter) if self.select_cb.is_some() => { Event::Key(Key::Enter) if self.on_submit.is_some() => {
let cb = self.select_cb.as_ref().unwrap().clone(); let cb = self.on_submit.clone().unwrap();
let v = self.selection(); let v = self.selection();
// We return a Callback Rc<|s| cb(s, &*v)> // We return a Callback Rc<|s| cb(s, &*v)>
return EventResult::Consumed(Some(Callback::from_fn(move |s| { return EventResult::Consumed(Some(Callback::from_fn(move |s| {
cb(s, &*v) cb(s, &v)
}))); })));
} }
Event::Char(c) => { Event::Char(c) => {
@ -394,7 +414,11 @@ impl<T: 'static> View for SelectView<T> {
} }
let focus = self.focus(); let focus = self.focus();
self.scrollbase.scroll_to(focus); self.scrollbase.scroll_to(focus);
EventResult::Consumed(None)
EventResult::Consumed(self.on_select.clone().map(|cb| {
let v = self.selection();
Callback::from_fn(move |s| cb(s, &v))
}))
} }
} }
@ -424,4 +448,3 @@ impl<T> Item<T> {
} }
} }
} }