use std::any::Any;
use view::{View, ViewPath, ViewWrapper};
use views::IdView;
pub trait Finder {
fn call_on<V, F, R>(&mut self, sel: &Selector, callback: F) -> Option<R>
where
V: View + Any,
F: FnOnce(&mut V) -> R;
fn find_id<V, F, R>(&mut self, id: &str, callback: F) -> Option<R>
where
V: View + Any,
F: FnOnce(&mut V) -> R,
{
self.call_on(&Selector::Id(id), callback)
}
}
impl<T: View> Finder for T {
fn call_on<V, F, R>(&mut self, sel: &Selector, callback: F) -> Option<R>
where
V: View + Any,
F: FnOnce(&mut V) -> R,
{
let mut result = None;
{
let result_ref = &mut result;
let mut callback = Some(callback);
let callback = |v: &mut Any| {
if let Some(callback) = callback.take() {
if v.is::<V>() {
*result_ref =
v.downcast_mut::<V>().map(|v| callback(v));
} else if v.is::<IdView<V>>() {
*result_ref = v
.downcast_mut::<IdView<V>>()
.and_then(|v| v.with_view_mut(callback));
}
}
};
self.call_on_any(sel, Box::new(callback));
}
result
}
}
pub enum Selector<'a> {
Id(&'a str),
Path(&'a ViewPath),
}