diff --git a/src/cursive.rs b/src/cursive.rs index 4045424..9b918bf 100644 --- a/src/cursive.rs +++ b/src/cursive.rs @@ -9,7 +9,7 @@ use std::path::Path; use std::sync::mpsc; use theme; use vec::Vec2; -use view::{self, AnyView, BoxableView, Finder, Position, View}; +use view::{self, AnyView, IntoBoxedView, Finder, Position, View}; use views::{self, LayerPosition}; /// Identifies a screen in the cursive root. @@ -456,7 +456,7 @@ impl Cursive { /// ``` pub fn add_layer(&mut self, view: T) where - T: BoxableView, + T: IntoBoxedView, { self.screen_mut().add_layer(view); } @@ -466,7 +466,7 @@ impl Cursive { /// Fullscreen layers have no shadow. pub fn add_fullscreen_layer(&mut self, view: T) where - T: BoxableView, + T: IntoBoxedView, { self.screen_mut().add_fullscreen_layer(view); } diff --git a/src/view/internal.rs b/src/view/internal.rs new file mode 100644 index 0000000..e2ce83c --- /dev/null +++ b/src/view/internal.rs @@ -0,0 +1,23 @@ +//! Internal module for some implementation details. +//! +//! You probable are not interested in anything here. These elements are +//! required to be public, but you should never need to use them directly. + +use view::{View, AnyView}; + +/// A trait for elements that can be converted to `AnyView`. +/// +/// You should never need to implement this yourself; it is automatically +/// implemented for any `T: View`. +/// +/// Just ignore this trait entirely. +pub trait ToAny { + /// Converts a boxed `Self` to a boxed `AnyView`. + fn to_any(self: Box) -> Box; +} + +impl ToAny for T { + fn to_any(self: Box) -> Box { + self + } +} diff --git a/src/view/into_boxed_view.rs b/src/view/into_boxed_view.rs new file mode 100644 index 0000000..b56e755 --- /dev/null +++ b/src/view/into_boxed_view.rs @@ -0,0 +1,28 @@ +use view::{AnyView, View}; + +/// Represents a type that can be made into a `Box`. +pub trait IntoBoxedView { + /// Returns a `Box`. + fn as_boxed_view(self) -> Box; +} + +impl IntoBoxedView for T +where + T: View, +{ + fn as_boxed_view(self) -> Box { + Box::new(self) + } +} + +impl IntoBoxedView for Box { + fn as_boxed_view(self) -> Box { + self + } +} + +impl IntoBoxedView for Box { + fn as_boxed_view(self) -> Box { + self.to_any() + } +} diff --git a/src/view/mod.rs b/src/view/mod.rs index 2284eec..adb608f 100644 --- a/src/view/mod.rs +++ b/src/view/mod.rs @@ -49,6 +49,11 @@ mod scroll; mod identifiable; mod boxable; +mod into_boxed_view; + +pub mod internal; + +pub use self::into_boxed_view::IntoBoxedView; pub use self::boxable::Boxable; pub use self::identifiable::Identifiable; pub use self::position::{Offset, Position}; @@ -107,31 +112,13 @@ impl AnyView for T { } } -/// Represents a type that can be made into a `Box`. -pub trait BoxableView { - /// Returns a `Box`. - fn as_boxed_view(self) -> Box; -} - -impl BoxableView for T -where - T: View, -{ - fn as_boxed_view(self) -> Box { - Box::new(self) - } -} - -impl BoxableView for Box { - fn as_boxed_view(self) -> Box { - self - } -} - /// Main trait defining a view behaviour. /// /// This is what you should implement to define a custom View. -pub trait View: Any { +/// +/// You can ignore the `Any` and `ToAny` trait bound; +/// they are implementation details, and will be implemented automatically. +pub trait View: Any + internal::ToAny { /// Called when a key was pressed. /// /// Default implementation just ignores it. diff --git a/src/views/any_box.rs b/src/views/any_box.rs index 5901104..b148552 100644 --- a/src/views/any_box.rs +++ b/src/views/any_box.rs @@ -1,7 +1,9 @@ use std::ops::{Deref, DerefMut}; -use view::{AnyView, BoxableView, ViewWrapper}; +use view::{AnyView, IntoBoxedView, ViewWrapper}; /// A boxed `AnyView`. +/// +/// It derefs to the wrapped view. pub struct AnyBox { view: Box, } @@ -13,7 +15,7 @@ impl AnyBox { } /// Box the given view - pub fn boxed(view: T) -> Self { + pub fn boxed(view: T) -> Self { AnyBox::new(view.as_boxed_view()) } diff --git a/src/views/stack_view.rs b/src/views/stack_view.rs index cbc5309..68eb405 100644 --- a/src/views/stack_view.rs +++ b/src/views/stack_view.rs @@ -7,7 +7,7 @@ use std::cell; use std::ops::Deref; use theme::ColorStyle; use vec::Vec2; -use view::{AnyView, BoxableView, Offset, Position, Selector, View, +use view::{AnyView, IntoBoxedView, Offset, Position, Selector, View, ViewWrapper}; use views::{AnyBox, Layer, ShadowView}; @@ -181,7 +181,7 @@ impl StackView { /// Fullscreen layers have no shadow. pub fn add_fullscreen_layer(&mut self, view: T) where - T: BoxableView, + T: IntoBoxedView, { let boxed = AnyBox::boxed(view); self.layers.push(Child { @@ -195,7 +195,7 @@ impl StackView { /// Adds new view on top of the stack in the center of the screen. pub fn add_layer(&mut self, view: T) where - T: BoxableView, + T: IntoBoxedView, { self.add_layer_at(Position::center(), view); } @@ -205,7 +205,7 @@ impl StackView { /// Chainable variant. pub fn layer(self, view: T) -> Self where - T: BoxableView, + T: IntoBoxedView, { self.with(|s| s.add_layer(view)) } @@ -266,7 +266,7 @@ impl StackView { /// Chainable variant. pub fn fullscreen_layer(self, view: T) -> Self where - T: BoxableView, + T: IntoBoxedView, { self.with(|s| s.add_fullscreen_layer(view)) } @@ -274,7 +274,7 @@ impl StackView { /// Adds a view on top of the stack. pub fn add_layer_at(&mut self, position: Position, view: T) where - T: BoxableView, + T: IntoBoxedView, { let boxed = AnyBox::boxed(view); self.layers.push(Child { @@ -295,7 +295,7 @@ impl StackView { /// Chainable variant. pub fn layer_at(self, position: Position, view: T) -> Self where - T: BoxableView, + T: IntoBoxedView, { self.with(|s| s.add_layer_at(position, view)) }