2019-02-28 23:54:12 +00:00
|
|
|
use crate::view::{View, ViewPath, ViewWrapper};
|
2020-01-06 20:10:24 +00:00
|
|
|
use crate::views::{NamedView, ViewRef};
|
2018-03-14 22:11:27 +00:00
|
|
|
|
|
|
|
/// Provides `call_on<V: View>` to views.
|
|
|
|
///
|
|
|
|
/// 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.
|
|
|
|
pub trait Finder {
|
2019-02-22 18:26:56 +00:00
|
|
|
/// Runs a callback on the view identified by `sel`.
|
|
|
|
///
|
|
|
|
/// If the view is found, return the result of `callback`.
|
2018-03-14 22:11:27 +00:00
|
|
|
///
|
|
|
|
/// If the view is not found, or if it is not of the asked type,
|
2019-02-22 18:26:56 +00:00
|
|
|
/// it returns `None`.
|
2019-03-01 00:04:14 +00:00
|
|
|
fn call_on<V, F, R>(
|
2019-07-30 23:08:05 +00:00
|
|
|
&mut self,
|
|
|
|
sel: &Selector<'_>,
|
|
|
|
callback: F,
|
2019-03-01 00:04:14 +00:00
|
|
|
) -> Option<R>
|
2018-03-14 22:11:27 +00:00
|
|
|
where
|
2020-03-03 21:08:55 +00:00
|
|
|
V: View,
|
2018-03-14 22:11:27 +00:00
|
|
|
F: FnOnce(&mut V) -> R;
|
|
|
|
|
2020-01-06 23:39:30 +00:00
|
|
|
/// Convenient method to use `call_on` with a `view::Selector::Name`.
|
|
|
|
fn call_on_name<V, F, R>(&mut self, name: &str, callback: F) -> Option<R>
|
|
|
|
where
|
2020-03-03 21:08:55 +00:00
|
|
|
V: View,
|
2020-01-06 23:39:30 +00:00
|
|
|
F: FnOnce(&mut V) -> R,
|
|
|
|
{
|
|
|
|
self.call_on(&Selector::Name(name), callback)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Same as [`call_on_name`](Finder::call_on_name).
|
|
|
|
#[deprecated(note = "`call_on_id` is being renamed to `call_on_name`")]
|
2019-02-21 19:16:04 +00:00
|
|
|
fn call_on_id<V, F, R>(&mut self, id: &str, callback: F) -> Option<R>
|
2018-03-14 22:11:27 +00:00
|
|
|
where
|
2020-03-03 21:08:55 +00:00
|
|
|
V: View,
|
2018-03-14 22:11:27 +00:00
|
|
|
F: FnOnce(&mut V) -> R,
|
|
|
|
{
|
2020-01-06 23:39:30 +00:00
|
|
|
self.call_on_name(id, callback)
|
2018-03-14 22:11:27 +00:00
|
|
|
}
|
2019-02-21 19:16:04 +00:00
|
|
|
|
2020-01-06 20:10:24 +00:00
|
|
|
/// Convenient method to find a view wrapped in an [`NamedView`].
|
2020-01-06 23:39:30 +00:00
|
|
|
fn find_name<V>(&mut self, name: &str) -> Option<ViewRef<V>>
|
|
|
|
where
|
2020-03-03 21:08:55 +00:00
|
|
|
V: View,
|
2020-01-06 23:39:30 +00:00
|
|
|
{
|
|
|
|
self.call_on_name(name, NamedView::<V>::get_mut)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Same as [`find_name`](Finder::find_name()).
|
|
|
|
#[deprecated(note = "`find_id` is being renamed to `find_name`")]
|
2019-02-21 19:16:04 +00:00
|
|
|
fn find_id<V>(&mut self, id: &str) -> Option<ViewRef<V>>
|
|
|
|
where
|
2020-03-03 21:08:55 +00:00
|
|
|
V: View,
|
2019-02-21 19:16:04 +00:00
|
|
|
{
|
2020-01-06 23:39:30 +00:00
|
|
|
self.find_name(id)
|
2019-02-21 19:16:04 +00:00
|
|
|
}
|
2018-03-14 22:11:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: View> Finder for T {
|
2019-03-01 00:04:14 +00:00
|
|
|
fn call_on<V, F, R>(
|
2019-07-30 23:08:05 +00:00
|
|
|
&mut self,
|
|
|
|
sel: &Selector<'_>,
|
|
|
|
callback: F,
|
2019-03-01 00:04:14 +00:00
|
|
|
) -> Option<R>
|
2018-03-14 22:11:27 +00:00
|
|
|
where
|
2020-03-03 21:08:55 +00:00
|
|
|
V: View,
|
2018-03-14 22:11:27 +00:00
|
|
|
F: FnOnce(&mut V) -> R,
|
|
|
|
{
|
|
|
|
let mut result = None;
|
|
|
|
{
|
|
|
|
let result_ref = &mut result;
|
|
|
|
|
|
|
|
let mut callback = Some(callback);
|
2020-03-03 21:08:55 +00:00
|
|
|
let mut callback = |v: &mut dyn View| {
|
2018-03-14 22:11:27 +00:00
|
|
|
if let Some(callback) = callback.take() {
|
|
|
|
if v.is::<V>() {
|
|
|
|
*result_ref =
|
|
|
|
v.downcast_mut::<V>().map(|v| callback(v));
|
2020-01-06 20:10:24 +00:00
|
|
|
} else if v.is::<NamedView<V>>() {
|
2020-03-03 21:08:55 +00:00
|
|
|
// Special case
|
2018-06-11 06:29:10 +00:00
|
|
|
*result_ref = v
|
2020-01-06 20:10:24 +00:00
|
|
|
.downcast_mut::<NamedView<V>>()
|
2018-03-14 22:11:27 +00:00
|
|
|
.and_then(|v| v.with_view_mut(callback));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2019-09-06 23:02:20 +00:00
|
|
|
self.call_on_any(sel, &mut callback);
|
2018-03-14 22:11:27 +00:00
|
|
|
}
|
|
|
|
result
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Selects a single view (if any) in the tree.
|
|
|
|
pub enum Selector<'a> {
|
2020-01-06 23:41:51 +00:00
|
|
|
/// Same as [`Selector::Name`].
|
2020-01-06 23:39:30 +00:00
|
|
|
#[deprecated(
|
|
|
|
note = "`Selector::Id` is being renamed to `Selector::Name`"
|
|
|
|
)]
|
2018-03-14 22:11:27 +00:00
|
|
|
Id(&'a str),
|
2020-01-06 20:10:24 +00:00
|
|
|
|
|
|
|
/// Selects a view from its name.
|
|
|
|
Name(&'a str),
|
|
|
|
|
2018-03-14 22:11:27 +00:00
|
|
|
/// Selects a view from its path.
|
|
|
|
Path(&'a ViewPath),
|
|
|
|
}
|