Use an associated type in ViewWrapper

This removes the need for dynamic dispatching
This commit is contained in:
Alexandre Bury 2016-09-19 17:11:00 -07:00
parent 3813f7c446
commit 08d1c1e5b0
8 changed files with 26 additions and 46 deletions

View File

@ -16,11 +16,14 @@ use event::{Event, EventResult};
///
/// [`wrap_impl!`]: ../macro.wrap_impl.html
pub trait ViewWrapper {
/// Type that this view wraps.
type V: View;
/// Get an immutable reference to the wrapped view.
fn get_view(&self) -> &View;
fn get_view(&self) -> &Self::V;
/// Get a mutable reference to the wrapped view.
fn get_view_mut(&mut self) -> &mut View;
fn get_view_mut(&mut self) -> &mut Self::V;
/// Wraps the `draw` method.
fn wrap_draw(&self, printer: &Printer) {
@ -90,27 +93,13 @@ impl<T: ViewWrapper> View for T {
/// Convenient macro to implement the [`ViewWrapper`] trait.
///
/// It defines the `get_view` and `get_view_mut` implementations,
/// as well as the `type V` declaration.
///
/// [`ViewWrapper`]: view/trait.ViewWrapper.html
///
/// # Examples
///
/// If the wrapped view is in a box, just name it in the macro:
///
/// ```no_run
/// # #[macro_use] extern crate cursive;
/// # use cursive::view::{View,ViewWrapper};
/// struct BoxFooView {
/// content: Box<View>,
/// }
///
/// impl ViewWrapper for BoxFooView {
/// wrap_impl!(self.content);
/// }
/// # fn main() { }
/// ```
///
/// If the content is directly a view, reference it:
///
/// ```no_run
/// # #[macro_use] extern crate cursive;
/// # use cursive::view::{View,ViewWrapper};
@ -119,30 +108,21 @@ impl<T: ViewWrapper> View for T {
/// }
///
/// impl <T: View> ViewWrapper for FooView<T> {
/// wrap_impl!(&self.view);
/// wrap_impl!(self.view: T);
/// }
/// # fn main() { }
/// ```
#[macro_export]
macro_rules! wrap_impl {
(&self.$v:ident) => {
(self.$v:ident: $t:path) => {
type V = $t;
fn get_view(&self) -> &View {
fn get_view(&self) -> &Self::V {
&self.$v
}
fn get_view_mut(&mut self) -> &mut View {
fn get_view_mut(&mut self) -> &mut Self::V {
&mut self.$v
}
};
(self.$v:ident) => {
fn get_view(&self) -> &View {
&*self.$v
}
fn get_view_mut(&mut self) -> &mut View {
&mut *self.$v
}
};
}

View File

@ -149,7 +149,7 @@ impl<T: View> BoxView<T> {
}
impl<T: View> ViewWrapper for BoxView<T> {
wrap_impl!(&self.view);
wrap_impl!(self.view: T);
fn wrap_get_min_size(&mut self, req: Vec2) -> Vec2 {

View File

@ -19,7 +19,7 @@ impl<T: View> IdView<T> {
}
impl<T: View + Any> ViewWrapper for IdView<T> {
wrap_impl!(&self.view);
wrap_impl!(self.view: T);
fn wrap_find(&mut self, selector: &Selector) -> Option<&mut Any> {
match selector {

View File

@ -16,16 +16,16 @@ use view::{View, ViewWrapper};
/// .register('q', |s| s.quit())
/// .register(Key::Esc, |s| s.quit());
/// ```
pub struct KeyEventView {
content: Box<View>,
pub struct KeyEventView<T: View> {
content: T,
callbacks: HashMap<Event, Callback>,
}
impl KeyEventView {
impl <T: View> KeyEventView<T> {
/// Wraps the given view in a new KeyEventView.
pub fn new<V: View + 'static>(view: V) -> Self {
pub fn new(view: T) -> Self {
KeyEventView {
content: Box::new(view),
content: view,
callbacks: HashMap::new(),
}
}
@ -40,8 +40,8 @@ impl KeyEventView {
}
}
impl ViewWrapper for KeyEventView {
wrap_impl!(self.content);
impl <T: View> ViewWrapper for KeyEventView<T> {
wrap_impl!(self.content: T);
fn wrap_on_event(&mut self, event: Event) -> EventResult {
match self.content.on_event(event) {

View File

@ -16,7 +16,7 @@ impl<V: View> Panel<V> {
impl<V: View> ViewWrapper for Panel<V> {
wrap_impl!(&self.view);
wrap_impl!(self.view: V);
fn wrap_get_min_size(&mut self, req: Vec2) -> Vec2 {
// TODO: make borders conditional?

View File

@ -45,7 +45,7 @@ impl<T: View> ShadowView<T> {
}
impl<T: View> ViewWrapper for ShadowView<T> {
wrap_impl!(&self.view);
wrap_impl!(self.view: T);
fn wrap_get_min_size(&mut self, req: Vec2) -> Vec2 {
// Make sure req >= offset

View File

@ -21,7 +21,7 @@ impl<T: View> SizedView<T> {
}
impl<T: View> ViewWrapper for SizedView<T> {
wrap_impl!(&self.view);
wrap_impl!(self.view: T);
fn wrap_layout(&mut self, size: Vec2) {
self.size = size;

View File

@ -36,7 +36,7 @@ impl<T: View> TrackedView<T> {
}
impl<T: View> ViewWrapper for TrackedView<T> {
wrap_impl!(&self.view);
wrap_impl!(self.view: T);
fn wrap_draw(&self, printer: &Printer) {
self.offset.set(printer.offset);