mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-23 17:35:00 +00:00
Rename KeyEventView to OnEventView
This commit is contained in:
parent
6fa062775b
commit
93b5421f53
@ -1,7 +1,7 @@
|
||||
extern crate cursive;
|
||||
|
||||
use cursive::Cursive;
|
||||
use cursive::views::{Dialog, KeyEventView, TextView};
|
||||
use cursive::views::{Dialog, OnEventView, TextView};
|
||||
use cursive::view::{Offset, Position};
|
||||
use cursive::traits::*;
|
||||
|
||||
@ -33,8 +33,8 @@ fn main() {
|
||||
// Let's wrap the view to give it a recognizable ID, so we can look for it.
|
||||
// We add the P callback on the textview only (and not globally),
|
||||
// so that we can't call it when the popup is already visible.
|
||||
siv.add_layer(KeyEventView::new(TextView::new(content).with_id("text"))
|
||||
.register('p', |s| show_popup(s)));
|
||||
siv.add_layer(OnEventView::new(TextView::new(content).with_id("text"))
|
||||
.on_event('p', |s| show_popup(s)));
|
||||
|
||||
|
||||
siv.run();
|
||||
|
@ -12,7 +12,7 @@ use std::rc::Rc;
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
use vec::Vec2;
|
||||
use view::{Position, ScrollBase, View};
|
||||
use views::KeyEventView;
|
||||
use views::OnEventView;
|
||||
|
||||
/// Popup that shows a list of items.
|
||||
pub struct MenuPopup {
|
||||
@ -141,11 +141,11 @@ impl MenuPopup {
|
||||
let tree = tree.clone();
|
||||
let max_width = 4 +
|
||||
self.menu
|
||||
.children
|
||||
.iter()
|
||||
.map(Self::item_width)
|
||||
.max()
|
||||
.unwrap_or(1);
|
||||
.children
|
||||
.iter()
|
||||
.map(Self::item_width)
|
||||
.max()
|
||||
.unwrap_or(1);
|
||||
let offset = Vec2::new(max_width, self.focus);
|
||||
let action_cb = self.on_action.clone();
|
||||
|
||||
@ -153,7 +153,7 @@ impl MenuPopup {
|
||||
let action_cb = action_cb.clone();
|
||||
s.screen_mut()
|
||||
.add_layer_at(Position::parent(offset),
|
||||
KeyEventView::new(MenuPopup::new(tree.clone())
|
||||
OnEventView::new(MenuPopup::new(tree.clone())
|
||||
.on_action(move |s| {
|
||||
// This will happen when the subtree popup
|
||||
// activates something;
|
||||
@ -163,7 +163,7 @@ impl MenuPopup {
|
||||
action_cb.clone()(s);
|
||||
}
|
||||
}))
|
||||
.register(Key::Left, |s| s.pop_layer()));
|
||||
.on_event(Key::Left, |s| s.pop_layer()));
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -219,11 +219,11 @@ impl View for MenuPopup {
|
||||
// We can't really shrink our items here, so it's not flexible.
|
||||
let w = 4 +
|
||||
self.menu
|
||||
.children
|
||||
.iter()
|
||||
.map(Self::item_width)
|
||||
.max()
|
||||
.unwrap_or(1);
|
||||
.children
|
||||
.iter()
|
||||
.map(Self::item_width)
|
||||
.max()
|
||||
.unwrap_or(1);
|
||||
let h = 2 + self.menu.children.len();
|
||||
|
||||
|
||||
@ -254,38 +254,38 @@ impl View for MenuPopup {
|
||||
Event::Key(Key::End) => self.focus = self.menu.children.len() - 1,
|
||||
|
||||
Event::Key(Key::Right) if self.menu.children[self.focus]
|
||||
.is_subtree() => {
|
||||
.is_subtree() => {
|
||||
return match self.menu.children[self.focus] {
|
||||
MenuItem::Subtree(_, ref tree) => {
|
||||
self.make_subtree_cb(tree)
|
||||
}
|
||||
_ => panic!("Not a subtree???"),
|
||||
MenuItem::Subtree(_, ref tree) => {
|
||||
self.make_subtree_cb(tree)
|
||||
}
|
||||
_ => panic!("Not a subtree???"),
|
||||
|
||||
};
|
||||
};
|
||||
}
|
||||
Event::Key(Key::Enter) if !self.menu.children[self.focus]
|
||||
.is_delimiter() => {
|
||||
.is_delimiter() => {
|
||||
return match self.menu.children[self.focus] {
|
||||
MenuItem::Leaf(_, ref cb) => {
|
||||
MenuItem::Leaf(_, ref cb) => {
|
||||
|
||||
let cb = cb.clone();
|
||||
let action_cb = self.on_action.clone();
|
||||
EventResult::with_cb(move |s| {
|
||||
// Remove ourselves from the face of the earth
|
||||
s.pop_layer();
|
||||
// If we had prior orders, do it now.
|
||||
if let Some(ref action_cb) = action_cb {
|
||||
action_cb.clone()(s);
|
||||
}
|
||||
// And transmit his last words.
|
||||
cb.clone()(s);
|
||||
})
|
||||
}
|
||||
MenuItem::Subtree(_, ref tree) => {
|
||||
self.make_subtree_cb(tree)
|
||||
}
|
||||
_ => panic!("No delimiter here"),
|
||||
};
|
||||
let cb = cb.clone();
|
||||
let action_cb = self.on_action.clone();
|
||||
EventResult::with_cb(move |s| {
|
||||
// Remove ourselves from the face of the earth
|
||||
s.pop_layer();
|
||||
// If we had prior orders, do it now.
|
||||
if let Some(ref action_cb) = action_cb {
|
||||
action_cb.clone()(s);
|
||||
}
|
||||
// And transmit his last words.
|
||||
cb.clone()(s);
|
||||
})
|
||||
}
|
||||
MenuItem::Subtree(_, ref tree) => {
|
||||
self.make_subtree_cb(tree)
|
||||
}
|
||||
_ => panic!("No delimiter here"),
|
||||
};
|
||||
}
|
||||
|
||||
_ => return EventResult::Ignored,
|
||||
@ -297,7 +297,6 @@ impl View for MenuPopup {
|
||||
}
|
||||
|
||||
fn layout(&mut self, size: Vec2) {
|
||||
self.scrollbase
|
||||
.set_heights(size.y - 2, self.menu.children.len());
|
||||
self.scrollbase.set_heights(size.y - 2, self.menu.children.len());
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ use theme::ColorStyle;
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
use vec::Vec2;
|
||||
use view::{Position, View};
|
||||
use views::{KeyEventView, MenuPopup};
|
||||
use views::{OnEventView, MenuPopup};
|
||||
|
||||
/// Current state of the menubar
|
||||
#[derive(PartialEq, Debug)]
|
||||
@ -108,9 +108,7 @@ impl Menubar {
|
||||
///
|
||||
/// Returns `None` if `i > self.len()`
|
||||
pub fn get_subtree(&mut self, i: usize) -> Option<&mut MenuTree> {
|
||||
self.menus
|
||||
.get_mut(i)
|
||||
.map(|&mut (_, ref mut tree)| Rc::make_mut(tree))
|
||||
self.menus.get_mut(i).map(|&mut (_, ref mut tree)| Rc::make_mut(tree))
|
||||
}
|
||||
|
||||
/// Looks for an item with the given label.
|
||||
@ -129,9 +127,7 @@ impl Menubar {
|
||||
///
|
||||
/// Returns `None` if no such label was found.
|
||||
pub fn find_position(&mut self, label: &str) -> Option<usize> {
|
||||
self.menus
|
||||
.iter()
|
||||
.position(|&(ref l, _)| l == label)
|
||||
self.menus.iter().position(|&(ref l, _)| l == label)
|
||||
}
|
||||
|
||||
/// Remove the item at the given position.
|
||||
@ -145,37 +141,38 @@ fn show_child(s: &mut Cursive, offset: (usize, usize), menu: Rc<MenuTree>) {
|
||||
// Also adds two key callbacks on this new view, to handle `left` and
|
||||
// `right` key presses.
|
||||
// (If the view itself listens for a `left` or `right` press, it will
|
||||
// consume it before our KeyEventView. This means sub-menus can properly
|
||||
// consume it before our OnEventView. This means sub-menus can properly
|
||||
// be entered.)
|
||||
s.screen_mut()
|
||||
.add_layer_at(Position::absolute(offset),
|
||||
KeyEventView::new(MenuPopup::new(menu)
|
||||
.on_dismiss(|s| s.select_menubar())
|
||||
.on_action(|s| {
|
||||
s.menubar().state = State::Inactive
|
||||
}))
|
||||
.register(Key::Right, |s| {
|
||||
s.pop_layer();
|
||||
s.select_menubar();
|
||||
// Act as if we sent "Right" then "Down"
|
||||
s.menubar().on_event(Event::Key(Key::Right)).process(s);
|
||||
if let EventResult::Consumed(Some(cb)) =
|
||||
s.menubar()
|
||||
.on_event(Event::Key(Key::Down)) {
|
||||
cb(s);
|
||||
}
|
||||
})
|
||||
.register(Key::Left, |s| {
|
||||
s.pop_layer();
|
||||
s.select_menubar();
|
||||
// Act as if we sent "Left" then "Down"
|
||||
s.menubar().on_event(Event::Key(Key::Left)).process(s);
|
||||
if let EventResult::Consumed(Some(cb)) =
|
||||
s.menubar()
|
||||
.on_event(Event::Key(Key::Down)) {
|
||||
cb(s);
|
||||
}
|
||||
}));
|
||||
OnEventView::new(MenuPopup::new(menu)
|
||||
.on_dismiss(|s| {
|
||||
s.select_menubar()
|
||||
})
|
||||
.on_action(|s| {
|
||||
s.menubar().state =
|
||||
State::Inactive
|
||||
}))
|
||||
.on_event(Key::Right, |s| {
|
||||
s.pop_layer();
|
||||
s.select_menubar();
|
||||
// Act as if we sent "Right" then "Down"
|
||||
s.menubar().on_event(Event::Key(Key::Right)).process(s);
|
||||
if let EventResult::Consumed(Some(cb)) =
|
||||
s.menubar().on_event(Event::Key(Key::Down)) {
|
||||
cb(s);
|
||||
}
|
||||
})
|
||||
.on_event(Key::Left, |s| {
|
||||
s.pop_layer();
|
||||
s.select_menubar();
|
||||
// Act as if we sent "Left" then "Down"
|
||||
s.menubar().on_event(Event::Key(Key::Left)).process(s);
|
||||
if let EventResult::Consumed(Some(cb)) =
|
||||
s.menubar().on_event(Event::Key(Key::Down)) {
|
||||
cb(s);
|
||||
}
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
@ -226,16 +223,19 @@ impl View for Menubar {
|
||||
// since we don't know when it will be called.
|
||||
let menu = self.menus[self.focus].1.clone();
|
||||
self.state = State::Submenu;
|
||||
let offset = (self.menus[..self.focus]
|
||||
.iter()
|
||||
.map(|&(ref title, _)| title.width() + 2)
|
||||
.fold(0, |a, b| a + b),
|
||||
if self.autohide { 1 } else { 0 });
|
||||
let offset =
|
||||
(self.menus[..self.focus]
|
||||
.iter()
|
||||
.map(|&(ref title, _)| title.width() + 2)
|
||||
.fold(0, |a, b| a + b),
|
||||
if self.autohide { 1 } else { 0 });
|
||||
// Since the closure will be called multiple times,
|
||||
// we also need a new Rc on every call.
|
||||
return EventResult::with_cb(move |s| {
|
||||
show_child(s, offset, menu.clone())
|
||||
});
|
||||
show_child(s,
|
||||
offset,
|
||||
menu.clone())
|
||||
});
|
||||
}
|
||||
_ => return EventResult::Ignored,
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ mod dialog;
|
||||
mod dummy;
|
||||
mod edit_view;
|
||||
mod id_view;
|
||||
mod key_event_view;
|
||||
mod on_event_view;
|
||||
mod layer;
|
||||
mod linear_layout;
|
||||
mod list_view;
|
||||
@ -69,7 +69,7 @@ pub use self::dialog::Dialog;
|
||||
pub use self::dummy::DummyView;
|
||||
pub use self::edit_view::EditView;
|
||||
pub use self::id_view::{IdView, ViewRef};
|
||||
pub use self::key_event_view::KeyEventView;
|
||||
pub use self::on_event_view::OnEventView;
|
||||
pub use self::layer::Layer;
|
||||
pub use self::linear_layout::LinearLayout;
|
||||
pub use self::list_view::{ListChild, ListView};
|
||||
|
@ -4,6 +4,7 @@ use Cursive;
|
||||
use event::{Callback, Event, EventResult};
|
||||
use std::collections::HashMap;
|
||||
use view::{View, ViewWrapper};
|
||||
use With;
|
||||
|
||||
/// A simple wrapper view that catches some ignored event from its child.
|
||||
///
|
||||
@ -13,36 +14,43 @@ use view::{View, ViewWrapper};
|
||||
///
|
||||
/// ```
|
||||
/// # use cursive::event;;
|
||||
/// # use cursive::views::{KeyEventView, TextView};
|
||||
/// let view = KeyEventView::new(TextView::new("This view has an event!"))
|
||||
/// .register('q', |s| s.quit())
|
||||
/// .register(event::Key::Esc, |s| s.quit());
|
||||
/// # use cursive::views::{OnEventView, TextView};
|
||||
/// let view = OnEventView::new(TextView::new("This view has an event!"))
|
||||
/// .on_event('q', |s| s.quit())
|
||||
/// .on_event(event::Key::Esc, |s| s.quit());
|
||||
/// ```
|
||||
pub struct KeyEventView<T: View> {
|
||||
pub struct OnEventView<T: View> {
|
||||
content: T,
|
||||
callbacks: HashMap<Event, Callback>,
|
||||
}
|
||||
|
||||
impl<T: View> KeyEventView<T> {
|
||||
/// Wraps the given view in a new KeyEventView.
|
||||
impl<T: View> OnEventView<T> {
|
||||
/// Wraps the given view in a new OnEventView.
|
||||
pub fn new(view: T) -> Self {
|
||||
KeyEventView {
|
||||
OnEventView {
|
||||
content: view,
|
||||
callbacks: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Registers a callback when the given key is ignored by the child.
|
||||
pub fn register<F, E: Into<Event>>(mut self, event: E, cb: F) -> Self
|
||||
/// Registers a callback when the given event is ignored by the child.
|
||||
///
|
||||
/// Chainable variant.
|
||||
pub fn on_event<F, E: Into<Event>>(self, event: E, cb: F) -> Self
|
||||
where F: Fn(&mut Cursive) + 'static
|
||||
{
|
||||
self.with(|s| s.set_on_event(event, cb))
|
||||
}
|
||||
|
||||
/// Registers a callback when the given event is ignored by the child.
|
||||
pub fn set_on_event<F, E: Into<Event>>(&mut self, event: E, cb: F)
|
||||
where F: Fn(&mut Cursive) + 'static
|
||||
{
|
||||
self.callbacks.insert(event.into(), Callback::from_fn(cb));
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: View> ViewWrapper for KeyEventView<T> {
|
||||
impl<T: View> ViewWrapper for OnEventView<T> {
|
||||
wrap_impl!(self.content: T);
|
||||
|
||||
fn wrap_on_event(&mut self, event: Event) -> EventResult {
|
Loading…
Reference in New Issue
Block a user