Rename find -> call_on

And update tutorials
This commit is contained in:
Alexandre Bury 2017-03-26 20:50:50 -07:00
parent c3c69e7892
commit c300e0628d
9 changed files with 58 additions and 54 deletions

View File

@ -40,7 +40,7 @@ fn main() {
fn add_name(s: &mut Cursive) {
fn ok(s: &mut Cursive, name: &str) {
s.find_id("select", |view: &mut SelectView<String>| {
s.call_on_id("select", |view: &mut SelectView<String>| {
view.add_item_str(name)
});
s.pop_layer();
@ -53,7 +53,7 @@ fn add_name(s: &mut Cursive) {
.title("Enter a new name")
.button("Ok", |s| {
let name =
s.find_id("name", |view: &mut EditView| {
s.call_on_id("name", |view: &mut EditView| {
view.get_content().clone()
}).unwrap();
ok(s, &name);
@ -62,16 +62,11 @@ fn add_name(s: &mut Cursive) {
}
fn delete_name(s: &mut Cursive) {
let selection = s.find_id("select", |view: &mut SelectView<String>| {
view.selected_id()
}).unwrap();
match selection {
let mut select = s.find_id::<SelectView<String>>("select").unwrap();
match select.selected_id() {
None => s.add_layer(Dialog::info("No name to remove")),
Some(focus) => {
s.find_id("select", |view: &mut SelectView<String>| {
view.remove_item(focus)
});
select.remove_item(focus);
}
}
}
@ -232,7 +227,7 @@ Later, you can ask the Cursive root for this ID and get access to the view.
Just what we need!
Like `BoxView`, `IdView` can be used directly with [`IdView::new`], or through
the [`Identifiable`] trait. [`Cursive::find_id`] allows you to run a closure
the [`Identifiable`] trait. [`Cursive::call_on_id`] allows you to run a closure
on the view.
Here's what it looks like in action:
@ -244,7 +239,7 @@ fn add_name(s: &mut Cursive) {
.fixed_width(10))
.title("Enter a new name")
.button("Ok", |s| {
let name = s.find_id("name", |view: &mut EditView| {
let name = s.call_on_id("name", |view: &mut EditView| {
view.get_content().clone()
}).unwrap();
})
@ -253,7 +248,7 @@ fn add_name(s: &mut Cursive) {
```
We create the `EditView` with the id `"name"`, and we use `"name"` again when
calling `find_id`.
calling `call_on_id`.
Now we just need to do something with this name: add it to the list!
Remember the `SelectView` we created? Let's give it an ID too:
@ -272,7 +267,7 @@ That way, we can update it with a new item:
```rust,ignore
fn add_name(s: &mut Cursive) {
fn ok(s: &mut Cursive, name: &str) {
s.find_id("select", |view: &mut SelectView<String>| {
s.call_on_id("select", |view: &mut SelectView<String>| {
view.add_item_str(name);
});
s.pop_layer();
@ -284,7 +279,7 @@ fn add_name(s: &mut Cursive) {
.fixed_width(10))
.title("Enter a new name")
.button("Ok", |s| {
let name = s.find_id("name", |v: &mut EditView| {
let name = s.call_on_id("name", |v: &mut EditView| {
v.get_content().clone()
}).unwrap();
ok(s, &name);
@ -298,27 +293,30 @@ complicated:
```rust,ignore
fn delete_name(s: &mut Cursive) {
match s.find_id("select", |v: &mut SelectView<String>| {
v.selected_id()
}).unwrap() {
let mut select = s.find_id::<SelectView<String>>("select").unwrap();
match select.selected_id() {
None => s.add_layer(Dialog::info("No name to remove")),
Some(focus) => s.find_id("select", |v: &mut SelectView<String>| {
v.remove_item(focus)
}),
Some(focus) => {
select.remove_item(focus);
}
}
}
```
We use [`SelectView::selected_id`] and [`SelectView::remove_item`] to remove
the item currently selected, nothing too surprising.
We have to find the `SelectView` twice, otherwise we're still borrowing `s`
when we try to add a new layer - one of the quirks of the borrow checker.
But this time, instead of using `call_on_id`, we use `Cursive::find_id`:
this method returns a handle, through which we can mutate the view.
It uses `Rc` and `RefCell` under the hood to provide mutable access to the
view without borrowing the `Cursive` root, leaving us free to pop layers.
[`EditView`]: http://gyscos.github.io/Cursive/cursive/views/struct.EditView.html
[`IdView`]: http://gyscos.github.io/Cursive/cursive/views/struct.IdView.html
[`IdView::new`]: http://gyscos.github.io/Cursive/cursive/prelude/struct.IdView.html#method.around
[`Identifiable`]: http://gyscos.github.io/Cursive/cursive/view/trait.Identifiable.html
[`Cursive::find_id`]: http://gyscos.github.io/Cursive/cursive/struct.Cursive.html#method.find_id
[`Cursive::call_on_id`]: http://gyscos.github.io/Cursive/cursive/struct.Cursive.html#method.call_on_id
[`SelectView::selected_id`]: http://gyscos.github.io/Cursive/cursive/views/struct.SelectView.html#method.selected_id
[`SelectView::remove_item`]: http://gyscos.github.io/Cursive/cursive/views/struct.SelectView.html#method.remove_item

View File

@ -386,23 +386,23 @@ impl Cursive {
/// .with_id("text"));
///
/// siv.add_global_callback('p', |s| {
/// s.find(&view::Selector::Id("text"), |view: &mut views::TextView| {
/// s.call_on(&view::Selector::Id("text"), |view: &mut views::TextView| {
/// view.set_content("Text #2");
/// });
/// });
/// # }
/// ```
pub fn find<V, F, R>(&mut self, sel: &view::Selector, callback: F)
pub fn call_on<V, F, R>(&mut self, sel: &view::Selector, callback: F)
-> Option<R>
where V: View + Any,
F: FnOnce(&mut V) -> R
{
self.screen_mut().find(sel, callback)
self.screen_mut().call_on(sel, callback)
}
/// Tries to find the view identified by the given id.
///
/// Convenient method to use `find` with a `view::Selector::Id`.
/// Convenient method to use `call_on` with a `view::Selector::Id`.
///
/// # Examples
///
@ -427,7 +427,7 @@ impl Cursive {
where V: View + Any,
F: FnOnce(&mut V) -> R
{
self.find(&view::Selector::Id(id), callback)
self.call_on(&view::Selector::Id(id), callback)
}
/// Convenient method to find a view wrapped in [`IdView`].

View File

@ -116,14 +116,14 @@ pub trait View {
/// Finds the view identified by the given selector.
///
/// See [`Finder::find`] for a nicer interface, implemented for all views.
/// See [`Finder::call_on`] for a nicer interface, implemented for all views.
///
/// [`Finder::find`]: trait.Finder.html#method.find
/// [`Finder::call_on`]: trait.Finder.html#method.call_on
///
/// Returns None if the path doesn't lead to a view.
///
/// Default implementation always return `None`.
fn find_any<'a>(&mut self, _: &Selector, _: Box<FnMut(&mut Any) + 'a>) {
fn call_on_any<'a>(&mut self, _: &Selector, _: Box<FnMut(&mut Any) + 'a>) {
// TODO: FnMut -> FnOnce once it works
}
@ -146,33 +146,33 @@ pub trait View {
}
}
/// Provides `find<V: View>` to views.
/// Provides `call_on<V: View>` to views.
///
/// This trait is mostly a wrapper around [`View::find_any`].
/// This trait is mostly a wrapper around [`View::call_on_any`].
///
/// It provides a nicer interface to find a view when you know its type.
///
/// [`View::find_any`]: ./trait.View.html#method.find_any
/// [`View::call_on_any`]: ./trait.View.html#method.call_on_any
pub trait Finder {
/// Tries to find the view pointed to by the given selector.
///
/// If the view is not found, or if it is not of the asked type,
/// it returns None.
fn find<V, F, R>(&mut self, sel: &Selector, callback: F) -> Option<R>
fn call_on<V, F, R>(&mut self, sel: &Selector, callback: F) -> Option<R>
where V: View + Any,
F: FnOnce(&mut V) -> R;
/// Convenient method to use `find` with a `view::Selector::Id`.
/// Convenient method to use `call_on` with a `view::Selector::Id`.
fn find_id<V, F, R>(&mut self, id: &str, callback: F) -> Option<R>
where V: View + Any,
F: FnOnce(&mut V) -> R
{
self.find(&Selector::Id(id), callback)
self.call_on(&Selector::Id(id), callback)
}
}
impl<T: View> Finder for T {
fn find<V, F, R>(&mut self, sel: &Selector, callback: F) -> Option<R>
fn call_on<V, F, R>(&mut self, sel: &Selector, callback: F) -> Option<R>
where V: View + Any,
F: FnOnce(&mut V) -> R
{
@ -190,7 +190,7 @@ impl<T: View> Finder for T {
.and_then(|v| v.with_view_mut(callback));
}
};
self.find_any(sel, Box::new(callback));
self.call_on_any(sel, Box::new(callback));
}
result
}

View File

@ -52,9 +52,9 @@ pub trait ViewWrapper {
}
/// Wraps the `find` method.
fn wrap_find_any<'a>(&mut self, selector: &Selector,
fn wrap_call_on_any<'a>(&mut self, selector: &Selector,
callback: Box<FnMut(&mut Any) + 'a>) {
self.with_view_mut(|v| v.find_any(selector, callback));
self.with_view_mut(|v| v.call_on_any(selector, callback));
}
/// Wraps the `focus_view` method.
@ -89,9 +89,9 @@ impl<T: ViewWrapper> View for T {
self.wrap_take_focus(source)
}
fn find_any<'a>(&mut self, selector: &Selector,
fn call_on_any<'a>(&mut self, selector: &Selector,
callback: Box<FnMut(&mut Any) + 'a>) {
self.wrap_find_any(selector, callback)
self.wrap_call_on_any(selector, callback)
}
fn needs_relayout(&self) -> bool {

View File

@ -399,9 +399,9 @@ impl View for Dialog {
}
}
fn find_any<'a>(&mut self, selector: &Selector,
fn call_on_any<'a>(&mut self, selector: &Selector,
callback: Box<FnMut(&mut Any) + 'a>) {
self.content.find_any(selector, callback);
self.content.call_on_any(selector, callback);
}
fn focus_view(&mut self, selector: &Selector) -> Result<(), ()> {

View File

@ -1,7 +1,7 @@
use owning_ref::{RcRef, OwningHandle};
use std::any::Any;
use std::cell::{RefCell, RefMut};
use std::any::Any;
use std::rc::Rc;
use view::{Selector, View, ViewWrapper};
@ -12,6 +12,10 @@ pub struct IdView<V: View> {
}
/// Mutable reference to a view.
///
/// This behaves like a [`RefMut`], but without being tied to a lifetime.
///
/// [`RefMut`]: https://doc.rust-lang.org/std/cell/struct.RefMut.html
pub type ViewRef<V> = OwningHandle<RcRef<RefCell<V>>, RefMut<'static, V>>;
impl<V: View> IdView<V> {
@ -24,6 +28,8 @@ impl<V: View> IdView<V> {
}
/// Gets mutable access to the inner view.
///
/// This returns a `ViewRef<V>`, which implement `DerefMut<Target = V>`.
pub fn get_mut(&mut self) -> ViewRef<V> {
// TODO: return a standalone item (not tied to our lifetime)
// that bundles `self.view.clone()` and allow mutable reference to
@ -56,11 +62,11 @@ impl<T: View + 'static> ViewWrapper for IdView<T> {
.map(|mut v| f(&mut *v))
}
fn wrap_find_any<'a>(&mut self, selector: &Selector,
fn wrap_call_on_any<'a>(&mut self, selector: &Selector,
mut callback: Box<for<'b> FnMut(&'b mut Any) + 'a>) {
let result = match selector {
&Selector::Id(id) if id == self.id => callback(self),
s => self.view.borrow_mut().find_any(s, callback),
s => self.view.borrow_mut().call_on_any(s, callback),
};
result
}

View File

@ -395,10 +395,10 @@ impl View for LinearLayout {
}
}
fn find_any<'a>(&mut self, selector: &Selector,
fn call_on_any<'a>(&mut self, selector: &Selector,
mut callback: Box<FnMut(&mut Any) + 'a>) {
for child in &mut self.children {
child.view.find_any(selector, Box::new(|any| callback(any)));
child.view.call_on_any(selector, Box::new(|any| callback(any)));
}
}

View File

@ -313,12 +313,12 @@ impl View for ListView {
true
}
fn find_any<'a>(&mut self, selector: &Selector,
fn call_on_any<'a>(&mut self, selector: &Selector,
mut callback: Box<FnMut(&mut Any) + 'a>) {
for view in self.children
.iter_mut()
.filter_map(Child::view) {
view.find_any(selector, Box::new(|any| callback(any)));
view.call_on_any(selector, Box::new(|any| callback(any)));
}
}

View File

@ -180,10 +180,10 @@ impl View for StackView {
}
}
fn find_any<'a>(&mut self, selector: &Selector,
fn call_on_any<'a>(&mut self, selector: &Selector,
mut callback: Box<FnMut(&mut Any) + 'a>) {
for layer in &mut self.layers {
layer.view.find_any(selector, Box::new(|any| callback(any)));
layer.view.call_on_any(selector, Box::new(|any| callback(any)));
}
}