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 {
view_any!();
fn draw(&self, printer: &Printer) {
// We simply draw every event from the history.
for (y, line) in self.history.iter().enumerate() {

View File

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

View File

@ -9,7 +9,7 @@ use std::path::Path;
use std::sync::mpsc;
use theme;
use vec::Vec2;
use view::{self, Finder, View};
use view::{self, AnyView, Finder, View};
use views;
/// Identifies a screen in the cursive root.
@ -418,7 +418,7 @@ impl Cursive {
}
/// 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();
self.clear();
result

View File

@ -35,15 +35,6 @@
//! no matter what the request is. This means calling `View::layout()` with
//! 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]
mod view_wrapper;
@ -73,6 +64,23 @@ use std::any::Any;
use vec::Vec2;
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.
pub trait View: Any {
/// Called when a key was pressed.
@ -82,11 +90,6 @@ pub trait View: Any {
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.
///

View File

@ -78,7 +78,9 @@ pub trait ViewWrapper: 'static {
/// Wraps the `find` method.
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));
}
@ -98,8 +100,12 @@ pub trait ViewWrapper: 'static {
// Some types easily implement ViewWrapper.
// This includes Box<T: View>
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;
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.
impl<T: ViewWrapper> View for T {
view_any!();
fn draw(&self, printer: &Printer) {
self.wrap_draw(printer);
}
@ -142,7 +146,9 @@ impl<T: ViewWrapper> View for T {
}
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)
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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