mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-23 17:35:00 +00:00
Return view on pop_layer
Callbacks now often allow (and ignore) a return type.
This commit is contained in:
parent
1b7170e308
commit
bd9b6a695b
@ -394,9 +394,10 @@ impl Cursive {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Convenient method to remove a layer from the current screen.
|
/// Convenient method to remove a layer from the current screen.
|
||||||
pub fn pop_layer(&mut self) {
|
pub fn pop_layer(&mut self) -> Option<Box<View>> {
|
||||||
self.screen_mut().pop_layer();
|
let result = self.screen_mut().pop_layer();
|
||||||
self.clear();
|
self.clear();
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handles a key event when it was ignored by the current view
|
// Handles a key event when it was ignored by the current view
|
||||||
|
26
src/event.rs
26
src/event.rs
@ -27,8 +27,13 @@ pub struct Callback(Rc<Box<Fn(&mut Cursive)>>);
|
|||||||
|
|
||||||
impl Callback {
|
impl Callback {
|
||||||
/// Wraps the given function into a `Callback` object.
|
/// Wraps the given function into a `Callback` object.
|
||||||
pub fn from_fn<F: Fn(&mut Cursive) + 'static>(f: F) -> Self {
|
pub fn from_fn<F, R>(f: F) -> Self
|
||||||
Callback(Rc::new(Box::new(f)))
|
where
|
||||||
|
F: 'static + Fn(&mut Cursive) -> R,
|
||||||
|
{
|
||||||
|
Callback(Rc::new(Box::new(move |siv| {
|
||||||
|
f(siv);
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +73,10 @@ pub enum EventResult {
|
|||||||
|
|
||||||
impl EventResult {
|
impl EventResult {
|
||||||
/// Convenient method to create `Consumed(Some(f))`
|
/// Convenient method to create `Consumed(Some(f))`
|
||||||
pub fn with_cb<F: 'static + Fn(&mut Cursive)>(f: F) -> Self {
|
pub fn with_cb<F, R>(f: F) -> Self
|
||||||
|
where
|
||||||
|
F: 'static + Fn(&mut Cursive) -> R,
|
||||||
|
{
|
||||||
EventResult::Consumed(Some(Callback::from_fn(f)))
|
EventResult::Consumed(Some(Callback::from_fn(f)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,9 +253,9 @@ impl MouseEvent {
|
|||||||
/// Returns `None` if `self` is `WheelUp` or `WheelDown`.
|
/// Returns `None` if `self` is `WheelUp` or `WheelDown`.
|
||||||
pub fn button(&self) -> Option<MouseButton> {
|
pub fn button(&self) -> Option<MouseButton> {
|
||||||
match *self {
|
match *self {
|
||||||
MouseEvent::Press(btn) |
|
MouseEvent::Press(btn)
|
||||||
MouseEvent::Release(btn) |
|
| MouseEvent::Release(btn)
|
||||||
MouseEvent::Hold(btn) => Some(btn),
|
| MouseEvent::Hold(btn) => Some(btn),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -257,9 +265,9 @@ impl MouseEvent {
|
|||||||
/// This includes `Press`, `WheelUp` and `WheelDown`.
|
/// This includes `Press`, `WheelUp` and `WheelDown`.
|
||||||
pub fn grabs_focus(self) -> bool {
|
pub fn grabs_focus(self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
MouseEvent::Press(_) |
|
MouseEvent::Press(_)
|
||||||
MouseEvent::WheelUp |
|
| MouseEvent::WheelUp
|
||||||
MouseEvent::WheelDown => true,
|
| MouseEvent::WheelDown => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,18 +27,18 @@ pub struct Button {
|
|||||||
|
|
||||||
impl Button {
|
impl Button {
|
||||||
/// Creates a new button with the given content and callback.
|
/// Creates a new button with the given content and callback.
|
||||||
pub fn new<F, S: Into<String>>(label: S, cb: F) -> Self
|
pub fn new<F, R, S: Into<String>>(label: S, cb: F) -> Self
|
||||||
where
|
where
|
||||||
F: Fn(&mut Cursive) + 'static,
|
F: 'static + Fn(&mut Cursive) -> R,
|
||||||
{
|
{
|
||||||
let label = label.into();
|
let label = label.into();
|
||||||
Self::new_raw(format!("<{}>", label), cb)
|
Self::new_raw(format!("<{}>", label), cb)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new button without angle brackets.
|
/// Creates a new button without angle brackets.
|
||||||
pub fn new_raw<F, S: Into<String>>(label: S, cb: F) -> Self
|
pub fn new_raw<F, R, S: Into<String>>(label: S, cb: F) -> Self
|
||||||
where
|
where
|
||||||
F: Fn(&mut Cursive) + 'static,
|
F: 'static + Fn(&mut Cursive) -> R,
|
||||||
{
|
{
|
||||||
Button {
|
Button {
|
||||||
label: label.into(),
|
label: label.into(),
|
||||||
|
@ -25,9 +25,9 @@ struct ChildButton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ChildButton {
|
impl ChildButton {
|
||||||
pub fn new<F, S: Into<String>>(label: S, cb: F) -> Self
|
pub fn new<F, R, S: Into<String>>(label: S, cb: F) -> Self
|
||||||
where
|
where
|
||||||
F: Fn(&mut Cursive) + 'static,
|
F: 'static + Fn(&mut Cursive) -> R,
|
||||||
{
|
{
|
||||||
ChildButton {
|
ChildButton {
|
||||||
button: SizedView::new(Button::new(label, cb)),
|
button: SizedView::new(Button::new(label, cb)),
|
||||||
@ -125,9 +125,9 @@ impl Dialog {
|
|||||||
/// Adds a button to the dialog with the given label and callback.
|
/// Adds a button to the dialog with the given label and callback.
|
||||||
///
|
///
|
||||||
/// Consumes and returns self for easy chaining.
|
/// Consumes and returns self for easy chaining.
|
||||||
pub fn button<F, S: Into<String>>(mut self, label: S, cb: F) -> Self
|
pub fn button<F, R, S: Into<String>>(mut self, label: S, cb: F) -> Self
|
||||||
where
|
where
|
||||||
F: Fn(&mut Cursive) + 'static,
|
F: 'static + Fn(&mut Cursive) -> R,
|
||||||
{
|
{
|
||||||
self.buttons.push(ChildButton::new(label, cb));
|
self.buttons.push(ChildButton::new(label, cb));
|
||||||
|
|
||||||
@ -158,7 +158,7 @@ impl Dialog {
|
|||||||
|
|
||||||
/// Shortcut method to add a button that will dismiss the dialog.
|
/// Shortcut method to add a button that will dismiss the dialog.
|
||||||
pub fn dismiss_button<S: Into<String>>(self, label: S) -> Self {
|
pub fn dismiss_button<S: Into<String>>(self, label: S) -> Self {
|
||||||
self.button(label, |s| s.screen_mut().pop_layer())
|
self.button(label, |s| s.pop_layer())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the title of the dialog.
|
/// Sets the title of the dialog.
|
||||||
@ -226,9 +226,9 @@ impl Dialog {
|
|||||||
) {
|
) {
|
||||||
EventResult::Ignored if !self.buttons.is_empty() => {
|
EventResult::Ignored if !self.buttons.is_empty() => {
|
||||||
match event {
|
match event {
|
||||||
Event::Key(Key::Down) |
|
Event::Key(Key::Down)
|
||||||
Event::Key(Key::Tab) |
|
| Event::Key(Key::Tab)
|
||||||
Event::Shift(Key::Tab) => {
|
| Event::Shift(Key::Tab) => {
|
||||||
// Default to leftmost button when going down.
|
// Default to leftmost button when going down.
|
||||||
self.focus = Focus::Button(0);
|
self.focus = Focus::Button(0);
|
||||||
EventResult::Consumed(None)
|
EventResult::Consumed(None)
|
||||||
@ -365,7 +365,9 @@ impl Dialog {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let spacing = 3; //minimum distance to borders
|
let spacing = 3; //minimum distance to borders
|
||||||
let x = spacing + self.title_position.get_offset(len, printer.size.x - 2 * spacing);
|
let x = spacing
|
||||||
|
+ self.title_position
|
||||||
|
.get_offset(len, printer.size.x - 2 * spacing);
|
||||||
printer.with_high_border(false, |printer| {
|
printer.with_high_border(false, |printer| {
|
||||||
printer.print((x - 2, 0), "┤ ");
|
printer.print((x - 2, 0), "┤ ");
|
||||||
printer.print((x + len, 0), " ├");
|
printer.print((x + len, 0), " ├");
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
use Cursive;
|
use Cursive;
|
||||||
use Printer;
|
use Printer;
|
||||||
use With;
|
use With;
|
||||||
@ -376,8 +374,8 @@ impl View for MenuPopup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Event::Key(Key::Esc) |
|
Event::Key(Key::Esc)
|
||||||
Event::Mouse {
|
| Event::Mouse {
|
||||||
event: MouseEvent::Press(_),
|
event: MouseEvent::Press(_),
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
|
@ -18,7 +18,7 @@ use view::{View, ViewWrapper};
|
|||||||
///
|
///
|
||||||
/// "Inner" callbacks ([`on_event_inner`] and [`on_pre_event_inner`]) are given
|
/// "Inner" callbacks ([`on_event_inner`] and [`on_pre_event_inner`]) are given
|
||||||
/// a reference to the inner wrapped view (but not to the `Cursive` root). They
|
/// a reference to the inner wrapped view (but not to the `Cursive` root). They
|
||||||
/// can then return another callback, taking only a `&mut Cursive` root as
|
/// can then return another callback, taking only a `&mut Cursive` root as
|
||||||
/// argument.
|
/// argument.
|
||||||
///
|
///
|
||||||
/// "Simple" callbacks ([`on_event`] and [`on_pre_event`]) skip this first
|
/// "Simple" callbacks ([`on_event`] and [`on_pre_event`]) skip this first
|
||||||
@ -77,10 +77,10 @@ impl<T: View> OnEventView<T> {
|
|||||||
/// Registers a callback when the given event is ignored by the child.
|
/// Registers a callback when the given event is ignored by the child.
|
||||||
///
|
///
|
||||||
/// Chainable variant.
|
/// Chainable variant.
|
||||||
pub fn on_event<F, E>(self, event: E, cb: F) -> Self
|
pub fn on_event<F, R, E>(self, event: E, cb: F) -> Self
|
||||||
where
|
where
|
||||||
E: Into<Event>,
|
E: Into<Event>,
|
||||||
F: Fn(&mut Cursive) + 'static,
|
F: 'static + Fn(&mut Cursive) -> R,
|
||||||
{
|
{
|
||||||
self.with(|s| s.set_on_event(event, cb))
|
self.with(|s| s.set_on_event(event, cb))
|
||||||
}
|
}
|
||||||
@ -90,10 +90,10 @@ impl<T: View> OnEventView<T> {
|
|||||||
/// The child will never receive this event.
|
/// The child will never receive this event.
|
||||||
///
|
///
|
||||||
/// Chainable variant.
|
/// Chainable variant.
|
||||||
pub fn on_pre_event<F, E>(self, event: E, cb: F) -> Self
|
pub fn on_pre_event<F, R, E>(self, event: E, cb: F) -> Self
|
||||||
where
|
where
|
||||||
E: Into<Event>,
|
E: Into<Event>,
|
||||||
F: Fn(&mut Cursive) + 'static,
|
F: 'static + Fn(&mut Cursive) -> R,
|
||||||
{
|
{
|
||||||
self.with(|s| s.set_on_pre_event(event, cb))
|
self.with(|s| s.set_on_pre_event(event, cb))
|
||||||
}
|
}
|
||||||
@ -132,10 +132,10 @@ impl<T: View> OnEventView<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Registers a callback when the given event is ignored by the child.
|
/// Registers a callback when the given event is ignored by the child.
|
||||||
pub fn set_on_event<F, E>(&mut self, event: E, cb: F)
|
pub fn set_on_event<F, R, E>(&mut self, event: E, cb: F)
|
||||||
where
|
where
|
||||||
E: Into<Event>,
|
E: Into<Event>,
|
||||||
F: Fn(&mut Cursive) + 'static,
|
F: Fn(&mut Cursive) -> R + 'static,
|
||||||
{
|
{
|
||||||
let cb = Callback::from_fn(cb);
|
let cb = Callback::from_fn(cb);
|
||||||
let action =
|
let action =
|
||||||
@ -147,12 +147,13 @@ impl<T: View> OnEventView<T> {
|
|||||||
/// Registers a callback when the given event is received.
|
/// Registers a callback when the given event is received.
|
||||||
///
|
///
|
||||||
/// The child will never receive this event.
|
/// The child will never receive this event.
|
||||||
pub fn set_on_pre_event<F, E>(&mut self, event: E, cb: F)
|
pub fn set_on_pre_event<F, R, E>(&mut self, event: E, cb: F)
|
||||||
where
|
where
|
||||||
E: Into<Event>,
|
E: Into<Event>,
|
||||||
F: Fn(&mut Cursive) + 'static,
|
F: 'static + Fn(&mut Cursive) -> R,
|
||||||
{
|
{
|
||||||
let cb = Callback::from_fn(cb);
|
let cb = Callback::from_fn(cb);
|
||||||
|
// We want to clone the Callback every time we call the closure
|
||||||
let action =
|
let action =
|
||||||
move |_: &mut T| Some(EventResult::Consumed(Some(cb.clone())));
|
move |_: &mut T| Some(EventResult::Consumed(Some(cb.clone())));
|
||||||
|
|
||||||
|
@ -152,12 +152,14 @@ impl<T: 'static> SelectView<T> {
|
|||||||
/// The item currently selected will be given to the callback.
|
/// The item currently selected will be given to the callback.
|
||||||
///
|
///
|
||||||
/// 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, R, V: ?Sized>(&mut self, cb: F)
|
||||||
where
|
where
|
||||||
F: Fn(&mut Cursive, &V) + 'static,
|
F: 'static + Fn(&mut Cursive, &V) -> R,
|
||||||
T: Borrow<V>,
|
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());
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets a callback to be used when `<Enter>` is pressed.
|
/// Sets a callback to be used when `<Enter>` is pressed.
|
||||||
|
@ -6,7 +6,7 @@ use std::any::Any;
|
|||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use theme::ColorStyle;
|
use theme::ColorStyle;
|
||||||
use vec::Vec2;
|
use vec::Vec2;
|
||||||
use view::{Offset, Position, Selector, View};
|
use view::{Offset, Position, Selector, View, ViewWrapper};
|
||||||
use views::{Layer, ShadowView};
|
use views::{Layer, ShadowView};
|
||||||
|
|
||||||
/// Simple stack of views.
|
/// Simple stack of views.
|
||||||
@ -47,9 +47,20 @@ enum ChildWrapper<T: View> {
|
|||||||
Plain(Layer<T>),
|
Plain(Layer<T>),
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: use macros to make this less ugly?
|
impl<T: View> ChildWrapper<T> {
|
||||||
impl <T: View> View for ChildWrapper<T> {
|
fn unwrap(self) -> T {
|
||||||
|
match self {
|
||||||
|
// ShadowView::into_inner and Layer::into_inner can never fail.
|
||||||
|
ChildWrapper::Shadow(shadow) => {
|
||||||
|
shadow.into_inner().ok().unwrap().into_inner().ok().unwrap()
|
||||||
|
}
|
||||||
|
ChildWrapper::Plain(layer) => layer.into_inner().ok().unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: use macros to make this less ugly?
|
||||||
|
impl<T: View> View for ChildWrapper<T> {
|
||||||
fn draw(&self, printer: &Printer) {
|
fn draw(&self, printer: &Printer) {
|
||||||
match *self {
|
match *self {
|
||||||
ChildWrapper::Shadow(ref v) => v.draw(printer),
|
ChildWrapper::Shadow(ref v) => v.draw(printer),
|
||||||
@ -86,12 +97,15 @@ impl <T: View> View for ChildWrapper<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn call_on_any<'a>(
|
fn call_on_any<'a>(
|
||||||
&mut self, selector: &Selector,
|
&mut self, selector: &Selector, callback: Box<FnMut(&mut Any) + 'a>
|
||||||
callback: Box<FnMut(&mut Any) + 'a>,
|
|
||||||
) {
|
) {
|
||||||
match *self {
|
match *self {
|
||||||
ChildWrapper::Shadow(ref mut v) => v.call_on_any(selector, callback),
|
ChildWrapper::Shadow(ref mut v) => {
|
||||||
ChildWrapper::Plain(ref mut v) => v.call_on_any(selector, callback),
|
v.call_on_any(selector, callback)
|
||||||
|
}
|
||||||
|
ChildWrapper::Plain(ref mut v) => {
|
||||||
|
v.call_on_any(selector, callback)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +115,6 @@ impl <T: View> View for ChildWrapper<T> {
|
|||||||
ChildWrapper::Plain(ref mut v) => v.focus_view(selector),
|
ChildWrapper::Plain(ref mut v) => v.focus_view(selector),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Child {
|
struct Child {
|
||||||
@ -201,8 +214,8 @@ impl StackView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Remove the top-most layer.
|
/// Remove the top-most layer.
|
||||||
pub fn pop_layer(&mut self) {
|
pub fn pop_layer(&mut self) -> Option<Box<View>> {
|
||||||
self.layers.pop();
|
self.layers.pop().map(|child| child.view.unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes the offset of the current top view.
|
/// Computes the offset of the current top view.
|
||||||
|
Loading…
Reference in New Issue
Block a user