From 93b5421f530373515ab5b571eddd255e464228d9 Mon Sep 17 00:00:00 2001 From: Alexandre Bury Date: Mon, 12 Jun 2017 16:39:12 -0700 Subject: [PATCH] Rename KeyEventView to OnEventView --- examples/mutation.rs | 6 +- src/views/menu_popup.rs | 81 +++++++++--------- src/views/menubar.rs | 84 +++++++++---------- src/views/mod.rs | 4 +- .../{key_event_view.rs => on_event_view.rs} | 34 +++++--- 5 files changed, 108 insertions(+), 101 deletions(-) rename src/views/{key_event_view.rs => on_event_view.rs} (55%) diff --git a/examples/mutation.rs b/examples/mutation.rs index a7c9ba7..3afaea9 100644 --- a/examples/mutation.rs +++ b/examples/mutation.rs @@ -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(); diff --git a/src/views/menu_popup.rs b/src/views/menu_popup.rs index 2bee2e7..283b595 100644 --- a/src/views/menu_popup.rs +++ b/src/views/menu_popup.rs @@ -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()); } } diff --git a/src/views/menubar.rs b/src/views/menubar.rs index c3fdb40..d76a6bb 100644 --- a/src/views/menubar.rs +++ b/src/views/menubar.rs @@ -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 { - 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) { // 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, } diff --git a/src/views/mod.rs b/src/views/mod.rs index 3f53427..d5953fb 100644 --- a/src/views/mod.rs +++ b/src/views/mod.rs @@ -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}; diff --git a/src/views/key_event_view.rs b/src/views/on_event_view.rs similarity index 55% rename from src/views/key_event_view.rs rename to src/views/on_event_view.rs index 8206860..402de06 100644 --- a/src/views/key_event_view.rs +++ b/src/views/on_event_view.rs @@ -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 { +pub struct OnEventView { content: T, callbacks: HashMap, } -impl KeyEventView { - /// Wraps the given view in a new KeyEventView. +impl OnEventView { + /// 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>(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>(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>(&mut self, event: E, cb: F) where F: Fn(&mut Cursive) + 'static { self.callbacks.insert(event.into(), Callback::from_fn(cb)); - - self } } -impl ViewWrapper for KeyEventView { +impl ViewWrapper for OnEventView { wrap_impl!(self.content: T); fn wrap_on_event(&mut self, event: Event) -> EventResult {