mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-27 11:16:03 +00:00
feat: Add SelectView::select_{up,down}
This commit is contained in:
parent
6bb3e88c2e
commit
da6a92f508
@ -132,7 +132,8 @@ 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.
|
||||||
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.on_select = Some(Rc::new(cb));
|
self.on_select = Some(Rc::new(cb));
|
||||||
}
|
}
|
||||||
@ -141,7 +142,8 @@ impl<T: 'static> SelectView<T> {
|
|||||||
///
|
///
|
||||||
/// Chainable variant.
|
/// Chainable variant.
|
||||||
pub fn on_select<F>(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.with(|s| s.set_on_select(cb))
|
self.with(|s| s.set_on_select(cb))
|
||||||
}
|
}
|
||||||
@ -152,8 +154,9 @@ impl<T: 'static> SelectView<T> {
|
|||||||
///
|
///
|
||||||
/// Here, `V` can be `T` itself, or a type that can be borrowed from `T`.
|
/// Here, `V` can be `T` itself, or a type that can be borrowed from `T`.
|
||||||
pub fn set_on_submit<F, V: ?Sized>(&mut self, cb: F)
|
pub fn set_on_submit<F, V: ?Sized>(&mut self, cb: F)
|
||||||
where F: Fn(&mut Cursive, &V) + 'static,
|
where
|
||||||
T: Borrow<V>
|
F: Fn(&mut Cursive, &V) + 'static,
|
||||||
|
T: Borrow<V>,
|
||||||
{
|
{
|
||||||
self.on_submit = Some(Rc::new(move |s, t| cb(s, t.borrow())));
|
self.on_submit = Some(Rc::new(move |s, t| cb(s, t.borrow())));
|
||||||
}
|
}
|
||||||
@ -164,8 +167,9 @@ impl<T: 'static> SelectView<T> {
|
|||||||
///
|
///
|
||||||
/// Chainable variant.
|
/// Chainable variant.
|
||||||
pub fn on_submit<F, V: ?Sized>(self, cb: F) -> Self
|
pub fn on_submit<F, V: ?Sized>(self, cb: F) -> Self
|
||||||
where F: Fn(&mut Cursive, &V) + 'static,
|
where
|
||||||
T: Borrow<V>
|
F: Fn(&mut Cursive, &V) + 'static,
|
||||||
|
T: Borrow<V>,
|
||||||
{
|
{
|
||||||
self.with(|s| s.set_on_submit(cb))
|
self.with(|s| s.set_on_submit(cb))
|
||||||
}
|
}
|
||||||
@ -227,8 +231,9 @@ impl<T: 'static> SelectView<T> {
|
|||||||
|
|
||||||
/// Adds all items from from an iterator.
|
/// Adds all items from from an iterator.
|
||||||
pub fn add_all<S, I>(&mut self, iter: I)
|
pub fn add_all<S, I>(&mut self, iter: I)
|
||||||
where S: Into<String>,
|
where
|
||||||
I: IntoIterator<Item = (S, T)>
|
S: Into<String>,
|
||||||
|
I: IntoIterator<Item = (S, T)>,
|
||||||
{
|
{
|
||||||
for (s, t) in iter {
|
for (s, t) in iter {
|
||||||
self.add_item(s, t);
|
self.add_item(s, t);
|
||||||
@ -239,8 +244,9 @@ impl<T: 'static> SelectView<T> {
|
|||||||
///
|
///
|
||||||
/// Chainable variant.
|
/// Chainable variant.
|
||||||
pub fn with_all<S, I>(self, iter: I) -> Self
|
pub fn with_all<S, I>(self, iter: I) -> Self
|
||||||
where S: Into<String>,
|
where
|
||||||
I: IntoIterator<Item = (S, T)>
|
S: Into<String>,
|
||||||
|
I: IntoIterator<Item = (S, T)>,
|
||||||
{
|
{
|
||||||
self.with(|s| s.add_all(iter))
|
self.with(|s| s.add_all(iter))
|
||||||
}
|
}
|
||||||
@ -288,11 +294,27 @@ impl<T: 'static> SelectView<T> {
|
|||||||
self.scrollbase.scroll_to(i);
|
self.scrollbase.scroll_to(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn focus_up(&mut self, n: usize) {
|
/// Moves the selection up by the given number of rows.
|
||||||
|
pub fn select_up(&mut self, n: usize) {
|
||||||
|
self.focus_up(n);
|
||||||
let focus = self.focus();
|
let focus = self.focus();
|
||||||
self.focus.set(focus.saturating_sub(n));
|
self.scrollbase.scroll_to(focus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Moves the selection down by the given number of rows.
|
||||||
|
pub fn select_down(&mut self, n: usize) {
|
||||||
|
self.focus_down(n);
|
||||||
|
let focus = self.focus();
|
||||||
|
self.scrollbase.scroll_to(focus);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Low-level focus change. Does not fix scrollbase.
|
||||||
|
fn focus_up(&mut self, n: usize) {
|
||||||
|
let focus = self.focus().saturating_sub(n);
|
||||||
|
self.focus.set(focus);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Low-level focus change. Does not fix scrollbase.
|
||||||
fn focus_down(&mut self, n: usize) {
|
fn focus_down(&mut self, n: usize) {
|
||||||
let focus = min(self.focus() + n, self.items.len().saturating_sub(1));
|
let focus = min(self.focus() + n, self.items.len().saturating_sub(1));
|
||||||
self.focus.set(focus);
|
self.focus.set(focus);
|
||||||
@ -321,8 +343,9 @@ impl SelectView<String> {
|
|||||||
/// select_view.add_all_str(vec!["a", "b", "c"]);
|
/// select_view.add_all_str(vec!["a", "b", "c"]);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn add_all_str<S, I>(&mut self, iter: I)
|
pub fn add_all_str<S, I>(&mut self, iter: I)
|
||||||
where S: Into<String>,
|
where
|
||||||
I: IntoIterator<Item = S>
|
S: Into<String>,
|
||||||
|
I: IntoIterator<Item = S>,
|
||||||
{
|
{
|
||||||
for s in iter {
|
for s in iter {
|
||||||
self.add_item_str(s);
|
self.add_item_str(s);
|
||||||
@ -333,8 +356,9 @@ impl SelectView<String> {
|
|||||||
///
|
///
|
||||||
/// Chainable variant.
|
/// Chainable variant.
|
||||||
pub fn with_all_str<S, I>(self, iter: I) -> Self
|
pub fn with_all_str<S, I>(self, iter: I) -> Self
|
||||||
where S: Into<String>,
|
where
|
||||||
I: IntoIterator<Item = S>
|
S: Into<String>,
|
||||||
|
I: IntoIterator<Item = S>,
|
||||||
{
|
{
|
||||||
self.with(|s| s.add_all_str(iter))
|
self.with(|s| s.add_all_str(iter))
|
||||||
}
|
}
|
||||||
@ -372,7 +396,6 @@ impl<T: 'static> View for SelectView<T> {
|
|||||||
printer.print((offset, 0), label);
|
printer.print((offset, 0), label);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
let h = self.items.len();
|
let h = self.items.len();
|
||||||
let offset = self.align.v.get_offset(h, printer.size.y);
|
let offset = self.align.v.get_offset(h, printer.size.y);
|
||||||
let printer =
|
let printer =
|
||||||
@ -465,9 +488,10 @@ impl<T: 'static> View for SelectView<T> {
|
|||||||
let current_offset = s.screen().offset();
|
let current_offset = s.screen().offset();
|
||||||
let offset = offset.signed() - current_offset;
|
let offset = offset.signed() - current_offset;
|
||||||
// And finally, put the view in view!
|
// And finally, put the view in view!
|
||||||
s.screen_mut().add_layer_at(Position::parent(offset),
|
s.screen_mut().add_layer_at(
|
||||||
MenuPopup::new(tree)
|
Position::parent(offset),
|
||||||
.focus(focus));
|
MenuPopup::new(tree).focus(focus),
|
||||||
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ => EventResult::Ignored,
|
_ => EventResult::Ignored,
|
||||||
@ -475,21 +499,24 @@ impl<T: 'static> View for SelectView<T> {
|
|||||||
} else {
|
} else {
|
||||||
match event {
|
match event {
|
||||||
Event::Key(Key::Up) if self.focus() > 0 => self.focus_up(1),
|
Event::Key(Key::Up) if self.focus() > 0 => self.focus_up(1),
|
||||||
Event::Key(Key::Down) if self.focus() + 1 <
|
Event::Key(Key::Down)
|
||||||
self.items.len() => {
|
if self.focus() + 1 < self.items.len() =>
|
||||||
|
{
|
||||||
self.focus_down(1)
|
self.focus_down(1)
|
||||||
}
|
}
|
||||||
Event::Key(Key::PageUp) => self.focus_up(10),
|
Event::Key(Key::PageUp) => self.focus_up(10),
|
||||||
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().saturating_sub(1)),
|
Event::Key(Key::End) => {
|
||||||
|
self.focus.set(self.items.len().saturating_sub(1))
|
||||||
|
}
|
||||||
Event::Key(Key::Enter) if self.on_submit.is_some() => {
|
Event::Key(Key::Enter) if self.on_submit.is_some() => {
|
||||||
let cb = self.on_submit.clone().unwrap();
|
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(
|
||||||
cb(s, &v)
|
Some(Callback::from_fn(move |s| cb(s, &v))),
|
||||||
})));
|
);
|
||||||
}
|
}
|
||||||
Event::Char(c) => {
|
Event::Char(c) => {
|
||||||
// Starting from the current focus,
|
// Starting from the current focus,
|
||||||
@ -498,10 +525,10 @@ impl<T: 'static> View for SelectView<T> {
|
|||||||
// the list when we reach the end.
|
// the list when we reach the end.
|
||||||
// This is achieved by chaining twice the iterator
|
// This is achieved by chaining twice the iterator
|
||||||
let iter = self.items.iter().chain(self.items.iter());
|
let iter = self.items.iter().chain(self.items.iter());
|
||||||
if let Some((i, _)) =
|
if let Some((i, _)) = iter.enumerate()
|
||||||
iter.enumerate()
|
|
||||||
.skip(self.focus() + 1)
|
.skip(self.focus() + 1)
|
||||||
.find(|&(_, item)| item.label.starts_with(c)) {
|
.find(|&(_, item)| item.label.starts_with(c))
|
||||||
|
{
|
||||||
// Apply modulo in case we have a hit
|
// Apply modulo in case we have a hit
|
||||||
// from the chained iterator
|
// from the chained iterator
|
||||||
self.focus.set(i % self.items.len());
|
self.focus.set(i % self.items.len());
|
||||||
|
Loading…
Reference in New Issue
Block a user