From 08d1c1e5b02b1aae15d7ca8890056a1f4b01a8de Mon Sep 17 00:00:00 2001 From: Alexandre Bury Date: Mon, 19 Sep 2016 17:11:00 -0700 Subject: [PATCH] Use an associated type in `ViewWrapper` This removes the need for dynamic dispatching --- src/view/view_wrapper.rs | 46 +++++++++++-------------------------- src/views/box_view.rs | 2 +- src/views/id_view.rs | 2 +- src/views/key_event_view.rs | 14 +++++------ src/views/panel.rs | 2 +- src/views/shadow_view.rs | 2 +- src/views/sized_view.rs | 2 +- src/views/tracked_view.rs | 2 +- 8 files changed, 26 insertions(+), 46 deletions(-) diff --git a/src/view/view_wrapper.rs b/src/view/view_wrapper.rs index c4529c3..986b05b 100644 --- a/src/view/view_wrapper.rs +++ b/src/view/view_wrapper.rs @@ -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 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, -/// } -/// -/// 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 View for T { /// } /// /// impl ViewWrapper for FooView { -/// 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 - } - }; } diff --git a/src/views/box_view.rs b/src/views/box_view.rs index 4793274..3a54ed7 100644 --- a/src/views/box_view.rs +++ b/src/views/box_view.rs @@ -149,7 +149,7 @@ impl BoxView { } impl ViewWrapper for BoxView { - wrap_impl!(&self.view); + wrap_impl!(self.view: T); fn wrap_get_min_size(&mut self, req: Vec2) -> Vec2 { diff --git a/src/views/id_view.rs b/src/views/id_view.rs index 102107f..423986c 100644 --- a/src/views/id_view.rs +++ b/src/views/id_view.rs @@ -19,7 +19,7 @@ impl IdView { } impl ViewWrapper for IdView { - wrap_impl!(&self.view); + wrap_impl!(self.view: T); fn wrap_find(&mut self, selector: &Selector) -> Option<&mut Any> { match selector { diff --git a/src/views/key_event_view.rs b/src/views/key_event_view.rs index 8d08ed7..8e9e05b 100644 --- a/src/views/key_event_view.rs +++ b/src/views/key_event_view.rs @@ -16,16 +16,16 @@ use view::{View, ViewWrapper}; /// .register('q', |s| s.quit()) /// .register(Key::Esc, |s| s.quit()); /// ``` -pub struct KeyEventView { - content: Box, +pub struct KeyEventView { + content: T, callbacks: HashMap, } -impl KeyEventView { +impl KeyEventView { /// Wraps the given view in a new KeyEventView. - pub fn new(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 ViewWrapper for KeyEventView { + wrap_impl!(self.content: T); fn wrap_on_event(&mut self, event: Event) -> EventResult { match self.content.on_event(event) { diff --git a/src/views/panel.rs b/src/views/panel.rs index 4c164e1..0324f7f 100644 --- a/src/views/panel.rs +++ b/src/views/panel.rs @@ -16,7 +16,7 @@ impl Panel { impl ViewWrapper for Panel { - wrap_impl!(&self.view); + wrap_impl!(self.view: V); fn wrap_get_min_size(&mut self, req: Vec2) -> Vec2 { // TODO: make borders conditional? diff --git a/src/views/shadow_view.rs b/src/views/shadow_view.rs index 562ff3f..7af92c0 100644 --- a/src/views/shadow_view.rs +++ b/src/views/shadow_view.rs @@ -45,7 +45,7 @@ impl ShadowView { } impl ViewWrapper for ShadowView { - wrap_impl!(&self.view); + wrap_impl!(self.view: T); fn wrap_get_min_size(&mut self, req: Vec2) -> Vec2 { // Make sure req >= offset diff --git a/src/views/sized_view.rs b/src/views/sized_view.rs index ad258e6..dc68a15 100644 --- a/src/views/sized_view.rs +++ b/src/views/sized_view.rs @@ -21,7 +21,7 @@ impl SizedView { } impl ViewWrapper for SizedView { - wrap_impl!(&self.view); + wrap_impl!(self.view: T); fn wrap_layout(&mut self, size: Vec2) { self.size = size; diff --git a/src/views/tracked_view.rs b/src/views/tracked_view.rs index 4d171be..822fce5 100644 --- a/src/views/tracked_view.rs +++ b/src/views/tracked_view.rs @@ -36,7 +36,7 @@ impl TrackedView { } impl ViewWrapper for TrackedView { - wrap_impl!(&self.view); + wrap_impl!(self.view: T); fn wrap_draw(&self, printer: &Printer) { self.offset.set(printer.offset);