Implement ViewWrapper for DerefMut<T: View>

This means View is implemented for Box<T: View>, Box<View>, ...
This commit is contained in:
Alexandre Bury 2017-09-24 12:24:23 -07:00
parent 1a4e1c104e
commit 607e6f1bdc
2 changed files with 44 additions and 47 deletions

View File

@ -148,42 +148,6 @@ pub trait View {
} }
} }
use std::ops::{Deref, DerefMut};
impl View for Box<View> {
fn draw(&self, printer: &Printer) {
self.deref().draw(printer)
}
fn required_size(&mut self, req: Vec2) -> Vec2 {
self.deref_mut().required_size(req)
}
fn on_event(&mut self, ch: Event) -> EventResult {
self.deref_mut().on_event(ch)
}
fn layout(&mut self, size: Vec2) {
self.deref_mut().layout(size);
}
fn take_focus(&mut self, source: Direction) -> bool {
self.deref_mut().take_focus(source)
}
fn call_on_any<'a>(&mut self, selector: &Selector,
callback: Box<FnMut(&mut Any) + 'a>) {
self.deref_mut().call_on_any(selector, callback)
}
fn needs_relayout(&self) -> bool {
self.deref().needs_relayout()
}
fn focus_view(&mut self, selector: &Selector) -> Result<(), ()> {
self.deref_mut().focus_view(selector)
}
}
/// Provides `call_on<V: View>` to views. /// Provides `call_on<V: View>` to views.
/// ///
/// This trait is mostly a wrapper around [`View::call_on_any`]. /// This trait is mostly a wrapper around [`View::call_on_any`].

View File

@ -17,14 +17,21 @@ use view::{Selector, View};
/// [`wrap_impl!`]: ../macro.wrap_impl.html /// [`wrap_impl!`]: ../macro.wrap_impl.html
pub trait ViewWrapper { pub trait ViewWrapper {
/// Type that this view wraps. /// Type that this view wraps.
type V: View; type V: View + ?Sized;
/// Get an immutable reference to the wrapped view. /// Get an immutable reference to the wrapped view.
fn with_view<F, R>(&self, f: F) -> Option<R> where F: FnOnce(&Self::V) -> R; ///
/// Returns `None` if the inner view is unavailable.
fn with_view<F, R>(&self, f: F) -> Option<R>
where
F: FnOnce(&Self::V) -> R;
/// Get a mutable reference to the wrapped view. /// Get a mutable reference to the wrapped view.
///
/// Returns `None` if the inner view is unavailable.
fn with_view_mut<F, R>(&mut self, f: F) -> Option<R> fn with_view_mut<F, R>(&mut self, f: F) -> Option<R>
where F: FnOnce(&mut Self::V) -> R; where
F: FnOnce(&mut Self::V) -> R;
/// Wraps the `draw` method. /// Wraps the `draw` method.
fn wrap_draw(&self, printer: &Printer) { fn wrap_draw(&self, printer: &Printer) {
@ -33,12 +40,15 @@ pub trait ViewWrapper {
/// Wraps the `required_size` method. /// Wraps the `required_size` method.
fn wrap_required_size(&mut self, req: Vec2) -> Vec2 { fn wrap_required_size(&mut self, req: Vec2) -> Vec2 {
self.with_view_mut(|v| v.required_size(req)).unwrap_or_else(Vec2::zero) self.with_view_mut(|v| v.required_size(req))
.unwrap_or_else(Vec2::zero)
} }
/// Wraps the `on_event` method. /// Wraps the `on_event` method.
fn wrap_on_event(&mut self, ch: Event) -> EventResult { fn wrap_on_event(&mut self, ch: Event) -> EventResult {
self.with_view_mut(|v| v.on_event(ch)).unwrap_or(EventResult::Ignored) self.with_view_mut(|v| v.on_event(ch)).unwrap_or(
EventResult::Ignored,
)
} }
/// Wraps the `layout` method. /// Wraps the `layout` method.
@ -48,18 +58,21 @@ pub trait ViewWrapper {
/// Wraps the `take_focus` method. /// Wraps the `take_focus` method.
fn wrap_take_focus(&mut self, source: Direction) -> bool { fn wrap_take_focus(&mut self, source: Direction) -> bool {
self.with_view_mut(|v| v.take_focus(source)).unwrap_or(false) self.with_view_mut(|v| v.take_focus(source)).unwrap_or(
false,
)
} }
/// Wraps the `find` method. /// Wraps the `find` method.
fn wrap_call_on_any<'a>(&mut self, selector: &Selector, fn wrap_call_on_any<'a>(&mut self, selector: &Selector, callback: Box<FnMut(&mut Any) + 'a>) {
callback: Box<FnMut(&mut Any) + 'a>) {
self.with_view_mut(|v| v.call_on_any(selector, callback)); self.with_view_mut(|v| v.call_on_any(selector, callback));
} }
/// Wraps the `focus_view` method. /// Wraps the `focus_view` method.
fn wrap_focus_view(&mut self, selector: &Selector) -> Result<(), ()> { fn wrap_focus_view(&mut self, selector: &Selector) -> Result<(), ()> {
self.with_view_mut(|v| v.focus_view(selector)).unwrap_or(Err(())) self.with_view_mut(|v| v.focus_view(selector)).unwrap_or(
Err(()),
)
} }
/// Wraps the `needs_relayout` method. /// Wraps the `needs_relayout` method.
@ -68,6 +81,27 @@ pub trait ViewWrapper {
} }
} }
use std::ops::{Deref, DerefMut};
impl<U: View + ?Sized, T: Deref<Target = U> + DerefMut> ViewWrapper for T {
type V = U;
/// Get an immutable reference to the wrapped view.
fn with_view<F, R>(&self, f: F) -> Option<R>
where
F: FnOnce(&Self::V) -> R,
{
Some(f(self.deref()))
}
/// Get a mutable reference to the wrapped view.
fn with_view_mut<F, R>(&mut self, f: F) -> Option<R>
where
F: FnOnce(&mut Self::V) -> R,
{
Some(f(self.deref_mut()))
}
}
impl<T: ViewWrapper> View for T { impl<T: ViewWrapper> View for T {
fn draw(&self, printer: &Printer) { fn draw(&self, printer: &Printer) {
self.wrap_draw(printer); self.wrap_draw(printer);
@ -89,8 +123,7 @@ impl<T: ViewWrapper> View for T {
self.wrap_take_focus(source) self.wrap_take_focus(source)
} }
fn call_on_any<'a>(&mut self, selector: &Selector, fn call_on_any<'a>(&mut self, selector: &Selector, callback: Box<FnMut(&mut Any) + 'a>) {
callback: Box<FnMut(&mut Any) + 'a>) {
self.wrap_call_on_any(selector, callback) self.wrap_call_on_any(selector, callback)
} }