Move View::as_any to separate trait AnyView

This commit is contained in:
Alexandre Bury 2018-01-22 11:50:25 -08:00
parent 1551fbb543
commit 98aff39904
22 changed files with 56 additions and 86 deletions

View File

@ -31,8 +31,6 @@ impl KeyCodeView {
} }
impl View for KeyCodeView { impl View for KeyCodeView {
view_any!();
fn draw(&self, printer: &Printer) { fn draw(&self, printer: &Printer) {
// We simply draw every event from the history. // We simply draw every event from the history.
for (y, line) in self.history.iter().enumerate() { for (y, line) in self.history.iter().enumerate() {

View File

@ -81,8 +81,6 @@ impl BufferView {
} }
impl View for BufferView { impl View for BufferView {
view_any!();
fn layout(&mut self, _: Vec2) { fn layout(&mut self, _: Vec2) {
// Before drawing, we'll want to update the buffer // Before drawing, we'll want to update the buffer
self.update(); self.update();

View File

@ -9,7 +9,7 @@ use std::path::Path;
use std::sync::mpsc; use std::sync::mpsc;
use theme; use theme;
use vec::Vec2; use vec::Vec2;
use view::{self, Finder, View}; use view::{self, AnyView, Finder, View};
use views; use views;
/// Identifies a screen in the cursive root. /// Identifies a screen in the cursive root.
@ -418,7 +418,7 @@ impl Cursive {
} }
/// Convenient method to remove a layer from the current screen. /// Convenient method to remove a layer from the current screen.
pub fn pop_layer(&mut self) -> Option<Box<View>> { pub fn pop_layer(&mut self) -> Option<Box<AnyView>> {
let result = self.screen_mut().pop_layer(); let result = self.screen_mut().pop_layer();
self.clear(); self.clear();
result result

View File

@ -35,15 +35,6 @@
//! no matter what the request is. This means calling `View::layout()` with //! no matter what the request is. This means calling `View::layout()` with
//! a size returned by `required_size` is **never** an error. //! a size returned by `required_size` is **never** an error.
/// Helper macro to implement `View::as_any` and `View::as_any_mut`
#[macro_export]
macro_rules! view_any {
() => {
fn as_any(&self) -> &::std::any::Any { self }
fn as_any_mut(&mut self) -> &mut ::std::any::Any { self }
}
}
#[macro_use] #[macro_use]
mod view_wrapper; mod view_wrapper;
@ -73,6 +64,23 @@ use std::any::Any;
use vec::Vec2; use vec::Vec2;
use views::IdView; use views::IdView;
/// A view that can be downcasted to its concrete type.
pub trait AnyView: View {
/// Downcast self to a `Any`.
fn as_any(&self) -> &Any;
/// Downcast self to a mutable `Any`.
fn as_any_mut(&mut self) -> &mut Any;
}
impl <T: View> AnyView for T {
/// Downcast self to a `Any`.
fn as_any(&self) -> &Any { self }
/// Downcast self to a mutable `Any`.
fn as_any_mut(&mut self) -> &mut Any { self }
}
/// Main trait defining a view behaviour. /// Main trait defining a view behaviour.
pub trait View: Any { pub trait View: Any {
/// Called when a key was pressed. /// Called when a key was pressed.
@ -82,11 +90,6 @@ pub trait View: Any {
EventResult::Ignored EventResult::Ignored
} }
/// Downcast self to a `Any`.
fn as_any(&self) -> &Any;
/// Downcast self to a mutable `Any`.
fn as_any_mut(&mut self) -> &mut Any;
/// Returns the minimum size the view requires with the given restrictions. /// Returns the minimum size the view requires with the given restrictions.
/// ///

View File

@ -78,7 +78,9 @@ pub trait ViewWrapper: 'static {
/// Wraps the `find` method. /// Wraps the `find` method.
fn wrap_call_on_any<'a>( fn wrap_call_on_any<'a>(
&mut self, selector: &Selector, callback: Box<FnMut(&mut Any) + 'a> &mut self,
selector: &Selector,
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));
} }
@ -98,8 +100,12 @@ pub trait ViewWrapper: 'static {
// Some types easily implement ViewWrapper. // Some types easily implement ViewWrapper.
// This includes Box<T: View> // This includes Box<T: View>
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
impl<U: View + ?Sized, T: Deref<Target = U> + DerefMut + 'static> ViewWrapper
for T { impl<U, T> ViewWrapper for T
where
U: View + ?Sized,
T: Deref<Target = U> + DerefMut + 'static,
{
type V = U; type V = U;
fn with_view<F, R>(&self, f: F) -> Option<R> fn with_view<F, R>(&self, f: F) -> Option<R>
@ -119,8 +125,6 @@ impl<U: View + ?Sized, T: Deref<Target = U> + DerefMut + 'static> ViewWrapper
// The main point of implementing ViewWrapper is to have View for free. // The main point of implementing ViewWrapper is to have View for free.
impl<T: ViewWrapper> View for T { impl<T: ViewWrapper> View for T {
view_any!();
fn draw(&self, printer: &Printer) { fn draw(&self, printer: &Printer) {
self.wrap_draw(printer); self.wrap_draw(printer);
} }
@ -142,7 +146,9 @@ impl<T: ViewWrapper> View for T {
} }
fn call_on_any<'a>( fn call_on_any<'a>(
&mut self, selector: &Selector, callback: Box<FnMut(&mut Any) + 'a> &mut self,
selector: &Selector,
callback: Box<FnMut(&mut Any) + 'a>,
) { ) {
self.wrap_call_on_any(selector, callback) self.wrap_call_on_any(selector, callback)
} }

View File

@ -126,8 +126,6 @@ impl Button {
} }
impl View for Button { impl View for Button {
view_any!();
fn draw(&self, printer: &Printer) { fn draw(&self, printer: &Printer) {
if printer.size.x == 0 { if printer.size.x == 0 {
return; return;

View File

@ -173,8 +173,6 @@ impl<T> Canvas<T> {
} }
impl<T: 'static> View for Canvas<T> { impl<T: 'static> View for Canvas<T> {
view_any!();
fn draw(&self, printer: &Printer) { fn draw(&self, printer: &Printer) {
(self.draw)(&self.state, printer); (self.draw)(&self.state, printer);
} }

View File

@ -105,8 +105,6 @@ impl Checkbox {
} }
impl View for Checkbox { impl View for Checkbox {
view_any!();
fn required_size(&mut self, _: Vec2) -> Vec2 { fn required_size(&mut self, _: Vec2) -> Vec2 {
Vec2::new(3, 1) Vec2::new(3, 1)
} }

View File

@ -10,7 +10,7 @@ use std::cmp::max;
use theme::ColorStyle; use theme::ColorStyle;
use unicode_width::UnicodeWidthStr; use unicode_width::UnicodeWidthStr;
use vec::{Vec2, Vec4}; use vec::{Vec2, Vec4};
use view::{Selector, View}; use view::{AnyView, Selector, View};
use views::{Button, DummyView, SizedView, TextView}; use views::{Button, DummyView, SizedView, TextView};
#[derive(PartialEq)] #[derive(PartialEq)]
@ -53,7 +53,7 @@ pub struct Dialog {
title_position: HAlign, title_position: HAlign,
// The actual inner view. // The actual inner view.
content: SizedView<Box<View>>, content: SizedView<Box<AnyView>>,
// Optional list of buttons under the main view. // Optional list of buttons under the main view.
// Include the top-left corner. // Include the top-left corner.
@ -423,8 +423,6 @@ impl Dialog {
} }
impl View for Dialog { impl View for Dialog {
view_any!();
fn draw(&self, printer: &Printer) { fn draw(&self, printer: &Printer) {
// This will be the buttons_height used by the buttons. // This will be the buttons_height used by the buttons.
let buttons_height = match self.draw_buttons(printer) { let buttons_height = match self.draw_buttons(printer) {

View File

@ -7,7 +7,5 @@ use view::View;
pub struct DummyView; pub struct DummyView;
impl View for DummyView { impl View for DummyView {
view_any!();
fn draw(&self, _: &Printer) {} fn draw(&self, _: &Printer) {}
} }

View File

@ -434,8 +434,6 @@ fn make_small_stars(length: usize) -> &'static str {
} }
impl View for EditView { impl View for EditView {
view_any!();
fn draw(&self, printer: &Printer) { fn draw(&self, printer: &Printer) {
assert_eq!( assert_eq!(
printer.size.x, printer.size.x,

View File

@ -7,8 +7,7 @@ use std::any::Any;
use std::cmp::min; use std::cmp::min;
use std::ops::Deref; use std::ops::Deref;
use vec::Vec2; use vec::Vec2;
use view::{Selector, SizeCache}; use view::{AnyView, View, Selector, SizeCache};
use view::View;
/// Arranges its children linearly according to its orientation. /// Arranges its children linearly according to its orientation.
pub struct LinearLayout { pub struct LinearLayout {
@ -20,7 +19,7 @@ pub struct LinearLayout {
} }
struct Child { struct Child {
view: Box<View>, view: Box<AnyView>,
// The last result from the child's required_size // The last result from the child's required_size
// Doesn't have to be what the child actually gets. // Doesn't have to be what the child actually gets.
size: Vec2, size: Vec2,
@ -34,7 +33,7 @@ impl Child {
self.size self.size
} }
fn as_view(&self) -> &View { fn as_view(&self) -> &AnyView {
&*self.view &*self.view
} }
} }
@ -161,12 +160,12 @@ impl LinearLayout {
} }
/// Returns a reference to a child. /// Returns a reference to a child.
pub fn get_child(&self, i: usize) -> Option<&View> { pub fn get_child(&self, i: usize) -> Option<&AnyView> {
self.children.get(i).map(|child| &*child.view) self.children.get(i).map(|child| &*child.view)
} }
/// Returns a mutable reference to a child. /// Returns a mutable reference to a child.
pub fn get_child_mut(&mut self, i: usize) -> Option<&mut View> { pub fn get_child_mut(&mut self, i: usize) -> Option<&mut AnyView> {
self.children.get_mut(i).map(|child| &mut *child.view) self.children.get_mut(i).map(|child| &mut *child.view)
} }
@ -297,8 +296,6 @@ fn try_focus(
} }
impl View for LinearLayout { impl View for LinearLayout {
view_any!();
fn draw(&self, printer: &Printer) { fn draw(&self, printer: &Printer) {
// Use pre-computed sizes // Use pre-computed sizes
// eprintln!("Pre loop!"); // eprintln!("Pre loop!");

View File

@ -7,16 +7,14 @@ use std::any::Any;
use std::rc::Rc; use std::rc::Rc;
use unicode_width::UnicodeWidthStr; use unicode_width::UnicodeWidthStr;
use vec::Vec2; use vec::Vec2;
use view::ScrollBase; use view::{AnyView, ScrollBase, Selector, View};
use view::Selector;
use view::View;
/// Represents a child from a [`ListView`]. /// Represents a child from a [`ListView`].
/// ///
/// [`ListView`]: struct.ListView.html /// [`ListView`]: struct.ListView.html
pub enum ListChild { pub enum ListChild {
/// A single row, with a label and a view. /// A single row, with a label and a view.
Row(String, Box<View>), Row(String, Box<AnyView>),
/// A delimiter between groups. /// A delimiter between groups.
Delimiter, Delimiter,
} }
@ -29,7 +27,7 @@ impl ListChild {
} }
} }
fn view(&mut self) -> Option<&mut View> { fn view(&mut self) -> Option<&mut AnyView> {
match *self { match *self {
ListChild::Row(_, ref mut view) => Some(view.as_mut()), ListChild::Row(_, ref mut view) => Some(view.as_mut()),
_ => None, _ => None,
@ -150,7 +148,9 @@ impl ListView {
} }
fn iter_mut<'a>( fn iter_mut<'a>(
&'a mut self, from_focus: bool, source: direction::Relative &'a mut self,
from_focus: bool,
source: direction::Relative,
) -> Box<Iterator<Item = (usize, &mut ListChild)> + 'a> { ) -> Box<Iterator<Item = (usize, &mut ListChild)> + 'a> {
match source { match source {
direction::Relative::Front => { direction::Relative::Front => {
@ -174,7 +174,9 @@ impl ListView {
} }
fn move_focus( fn move_focus(
&mut self, n: usize, source: direction::Direction &mut self,
n: usize,
source: direction::Direction,
) -> EventResult { ) -> EventResult {
let i = if let Some(i) = source let i = if let Some(i) = source
.relative(direction::Orientation::Vertical) .relative(direction::Orientation::Vertical)
@ -248,7 +250,8 @@ impl ListView {
} }
fn try_focus( fn try_focus(
(i, child): (usize, &mut ListChild), source: direction::Direction (i, child): (usize, &mut ListChild),
source: direction::Direction,
) -> Option<usize> { ) -> Option<usize> {
match *child { match *child {
ListChild::Delimiter => None, ListChild::Delimiter => None,
@ -261,9 +264,6 @@ fn try_focus(
} }
impl View for ListView { impl View for ListView {
view_any!();
fn draw(&self, printer: &Printer) { fn draw(&self, printer: &Printer) {
if self.children.is_empty() { if self.children.is_empty() {
return; return;
@ -454,7 +454,8 @@ impl View for ListView {
} }
fn call_on_any<'a>( fn call_on_any<'a>(
&mut self, selector: &Selector, &mut self,
selector: &Selector,
mut callback: Box<FnMut(&mut Any) + 'a>, mut callback: Box<FnMut(&mut Any) + 'a>,
) { ) {
for view in self.children.iter_mut().filter_map(ListChild::view) { for view in self.children.iter_mut().filter_map(ListChild::view) {

View File

@ -199,8 +199,6 @@ impl MenuPopup {
} }
impl View for MenuPopup { impl View for MenuPopup {
view_any!();
fn draw(&self, printer: &Printer) { fn draw(&self, printer: &Printer) {
if !printer.size.fits((2, 2)) { if !printer.size.fits((2, 2)) {
return; return;

View File

@ -259,8 +259,6 @@ fn show_child(s: &mut Cursive, offset: Vec2, menu: Rc<MenuTree>) {
} }
impl View for Menubar { impl View for Menubar {
view_any!();
fn draw(&self, printer: &Printer) { fn draw(&self, printer: &Printer) {
// Draw the bar at the top // Draw the bar at the top
printer.with_color(ColorStyle::primary(), |printer| { printer.with_color(ColorStyle::primary(), |printer| {

View File

@ -193,8 +193,6 @@ impl ProgressBar {
} }
impl View for ProgressBar { impl View for ProgressBar {
view_any!();
fn draw(&self, printer: &Printer) { fn draw(&self, printer: &Printer) {
// Now, the bar itself... // Now, the bar itself...
let available = printer.size.x; let available = printer.size.x;

View File

@ -154,9 +154,6 @@ impl<T> RadioButton<T> {
} }
impl<T: 'static> View for RadioButton<T> { impl<T: 'static> View for RadioButton<T> {
view_any!();
fn required_size(&mut self, _: Vec2) -> Vec2 { fn required_size(&mut self, _: Vec2) -> Vec2 {
self.req_size() self.req_size()
} }

View File

@ -570,8 +570,6 @@ impl SelectView<String> {
} }
impl<T: 'static> View for SelectView<T> { impl<T: 'static> View for SelectView<T> {
view_any!();
fn draw(&self, printer: &Printer) { fn draw(&self, printer: &Printer) {
self.last_offset.set(printer.offset); self.last_offset.set(printer.offset);

View File

@ -112,8 +112,6 @@ impl SliderView {
} }
impl View for SliderView { impl View for SliderView {
view_any!();
fn draw(&self, printer: &Printer) { fn draw(&self, printer: &Printer) {
match self.orientation { match self.orientation {
Orientation::Vertical => { Orientation::Vertical => {

View File

@ -6,7 +6,7 @@ use std::any::Any;
use std::ops::Deref; use std::ops::Deref;
use theme::ColorStyle; use theme::ColorStyle;
use vec::Vec2; use vec::Vec2;
use view::{Offset, Position, Selector, View, ViewWrapper}; use view::{AnyView, Offset, Position, Selector, View, ViewWrapper};
use views::{Layer, ShadowView}; use views::{Layer, ShadowView};
/// Simple stack of views. /// Simple stack of views.
@ -71,8 +71,6 @@ impl<T: View> ChildWrapper<T> {
// TODO: use macros to make this less ugly? // TODO: use macros to make this less ugly?
impl<T: View> View for ChildWrapper<T> { impl<T: View> View for ChildWrapper<T> {
view_any!();
fn draw(&self, printer: &Printer) { fn draw(&self, printer: &Printer) {
match *self { match *self {
ChildWrapper::Shadow(ref v) => v.draw(printer), ChildWrapper::Shadow(ref v) => v.draw(printer),
@ -130,7 +128,7 @@ impl<T: View> View for ChildWrapper<T> {
} }
struct Child { struct Child {
view: ChildWrapper<Box<View>>, view: ChildWrapper<Box<AnyView>>,
size: Vec2, size: Vec2,
placement: Placement, placement: Placement,
@ -159,7 +157,7 @@ impl StackView {
where where
T: 'static + View, T: 'static + View,
{ {
let boxed: Box<View> = Box::new(view); let boxed: Box<AnyView> = Box::new(view);
self.layers.push(Child { self.layers.push(Child {
view: ChildWrapper::Plain(Layer::new(boxed)), view: ChildWrapper::Plain(Layer::new(boxed)),
size: Vec2::zero(), size: Vec2::zero(),
@ -201,7 +199,7 @@ impl StackView {
where where
T: 'static + View, T: 'static + View,
{ {
let boxed: Box<View> = Box::new(view); let boxed: Box<AnyView> = Box::new(view);
self.layers.push(Child { self.layers.push(Child {
// Skip padding for absolute/parent-placed views // Skip padding for absolute/parent-placed views
view: ChildWrapper::Shadow( view: ChildWrapper::Shadow(
@ -226,7 +224,7 @@ impl StackView {
} }
/// Remove the top-most layer. /// Remove the top-most layer.
pub fn pop_layer(&mut self) -> Option<Box<View>> { pub fn pop_layer(&mut self) -> Option<Box<AnyView>> {
self.layers.pop().map(|child| child.view.unwrap()) self.layers.pop().map(|child| child.view.unwrap())
} }
@ -324,8 +322,6 @@ impl<R: Deref<Target = Child>, I: Iterator<Item = R>> Iterator
} }
impl View for StackView { impl View for StackView {
view_any!();
fn draw(&self, printer: &Printer) { fn draw(&self, printer: &Printer) {
let last = self.layers.len(); let last = self.layers.len();
printer.with_color(ColorStyle::primary(), |printer| { printer.with_color(ColorStyle::primary(), |printer| {

View File

@ -396,8 +396,6 @@ impl TextArea {
} }
impl View for TextArea { impl View for TextArea {
view_any!();
fn required_size(&mut self, constraint: Vec2) -> Vec2 { fn required_size(&mut self, constraint: Vec2) -> Vec2 {
// Make sure our structure is up to date // Make sure our structure is up to date
self.soft_compute_rows(constraint); self.soft_compute_rows(constraint);

View File

@ -448,8 +448,6 @@ impl TextView {
} }
impl View for TextView { impl View for TextView {
view_any!();
fn draw(&self, printer: &Printer) { fn draw(&self, printer: &Printer) {
let h = self.rows.len(); let h = self.rows.len();
// If the content is smaller than the view, align it somewhere. // If the content is smaller than the view, align it somewhere.