From 1551fbb543e5eece4a42cf9dcbe068942ea7b73f Mon Sep 17 00:00:00 2001 From: Alexandre Bury Date: Mon, 22 Jan 2018 09:20:32 -0800 Subject: [PATCH] Add View::as_any and View::as_any_mut --- examples/key_codes.rs | 3 +++ examples/logs.rs | 3 +++ src/view/mod.rs | 15 +++++++++++++++ src/view/view_wrapper.rs | 2 ++ src/views/button.rs | 2 ++ src/views/canvas.rs | 2 ++ src/views/checkbox.rs | 2 ++ src/views/dialog.rs | 2 ++ src/views/dummy.rs | 2 ++ src/views/edit_view.rs | 2 ++ src/views/linear_layout.rs | 2 ++ src/views/list_view.rs | 3 +++ src/views/menu_popup.rs | 2 ++ src/views/menubar.rs | 2 ++ src/views/progress_bar.rs | 2 ++ src/views/radio.rs | 3 +++ src/views/select_view.rs | 3 +++ src/views/slider_view.rs | 2 ++ src/views/stack_view.rs | 4 ++++ src/views/text_area.rs | 2 ++ src/views/text_view.rs | 2 ++ 21 files changed, 62 insertions(+) diff --git a/examples/key_codes.rs b/examples/key_codes.rs index ff64bc3..2b345b4 100644 --- a/examples/key_codes.rs +++ b/examples/key_codes.rs @@ -1,3 +1,4 @@ +#[macro_use] extern crate cursive; use cursive::{Cursive, Printer}; @@ -30,6 +31,8 @@ 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() { diff --git a/examples/logs.rs b/examples/logs.rs index 871f348..c1f33a0 100644 --- a/examples/logs.rs +++ b/examples/logs.rs @@ -1,3 +1,4 @@ +#[macro_use] extern crate cursive; use cursive::{Cursive, Printer}; @@ -80,6 +81,8 @@ impl BufferView { } impl View for BufferView { + view_any!(); + fn layout(&mut self, _: Vec2) { // Before drawing, we'll want to update the buffer self.update(); diff --git a/src/view/mod.rs b/src/view/mod.rs index 76fd604..ca21b01 100644 --- a/src/view/mod.rs +++ b/src/view/mod.rs @@ -35,6 +35,15 @@ //! 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 +82,12 @@ 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. /// /// If the view is flexible (it has multiple size options), it can try diff --git a/src/view/view_wrapper.rs b/src/view/view_wrapper.rs index c26dc02..208649e 100644 --- a/src/view/view_wrapper.rs +++ b/src/view/view_wrapper.rs @@ -119,6 +119,8 @@ impl + DerefMut + 'static> ViewWrapper // The main point of implementing ViewWrapper is to have View for free. impl View for T { + view_any!(); + fn draw(&self, printer: &Printer) { self.wrap_draw(printer); } diff --git a/src/views/button.rs b/src/views/button.rs index a0ec0fc..9f5ab11 100644 --- a/src/views/button.rs +++ b/src/views/button.rs @@ -126,6 +126,8 @@ impl Button { } impl View for Button { + view_any!(); + fn draw(&self, printer: &Printer) { if printer.size.x == 0 { return; diff --git a/src/views/canvas.rs b/src/views/canvas.rs index 8d5d7af..5766079 100644 --- a/src/views/canvas.rs +++ b/src/views/canvas.rs @@ -173,6 +173,8 @@ impl Canvas { } impl View for Canvas { + view_any!(); + fn draw(&self, printer: &Printer) { (self.draw)(&self.state, printer); } diff --git a/src/views/checkbox.rs b/src/views/checkbox.rs index 6f8aef4..3fd5ea8 100644 --- a/src/views/checkbox.rs +++ b/src/views/checkbox.rs @@ -105,6 +105,8 @@ impl Checkbox { } impl View for Checkbox { + view_any!(); + fn required_size(&mut self, _: Vec2) -> Vec2 { Vec2::new(3, 1) } diff --git a/src/views/dialog.rs b/src/views/dialog.rs index 3d7662d..17cabc8 100644 --- a/src/views/dialog.rs +++ b/src/views/dialog.rs @@ -423,6 +423,8 @@ 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) { diff --git a/src/views/dummy.rs b/src/views/dummy.rs index 5b88176..2123a50 100644 --- a/src/views/dummy.rs +++ b/src/views/dummy.rs @@ -7,5 +7,7 @@ use view::View; pub struct DummyView; impl View for DummyView { + view_any!(); + fn draw(&self, _: &Printer) {} } diff --git a/src/views/edit_view.rs b/src/views/edit_view.rs index 4a2b775..4faee7c 100644 --- a/src/views/edit_view.rs +++ b/src/views/edit_view.rs @@ -434,6 +434,8 @@ fn make_small_stars(length: usize) -> &'static str { } impl View for EditView { + view_any!(); + fn draw(&self, printer: &Printer) { assert_eq!( printer.size.x, diff --git a/src/views/linear_layout.rs b/src/views/linear_layout.rs index 9047859..f88606c 100644 --- a/src/views/linear_layout.rs +++ b/src/views/linear_layout.rs @@ -297,6 +297,8 @@ fn try_focus( } impl View for LinearLayout { + view_any!(); + fn draw(&self, printer: &Printer) { // Use pre-computed sizes // eprintln!("Pre loop!"); diff --git a/src/views/list_view.rs b/src/views/list_view.rs index 8c60b56..e419cd2 100644 --- a/src/views/list_view.rs +++ b/src/views/list_view.rs @@ -261,6 +261,9 @@ fn try_focus( } impl View for ListView { + view_any!(); + + fn draw(&self, printer: &Printer) { if self.children.is_empty() { return; diff --git a/src/views/menu_popup.rs b/src/views/menu_popup.rs index 365ec13..7da673e 100644 --- a/src/views/menu_popup.rs +++ b/src/views/menu_popup.rs @@ -199,6 +199,8 @@ impl MenuPopup { } impl View for MenuPopup { + view_any!(); + fn draw(&self, printer: &Printer) { if !printer.size.fits((2, 2)) { return; diff --git a/src/views/menubar.rs b/src/views/menubar.rs index abb83fc..b39dee3 100644 --- a/src/views/menubar.rs +++ b/src/views/menubar.rs @@ -259,6 +259,8 @@ fn show_child(s: &mut Cursive, offset: Vec2, menu: Rc) { } impl View for Menubar { + view_any!(); + fn draw(&self, printer: &Printer) { // Draw the bar at the top printer.with_color(ColorStyle::primary(), |printer| { diff --git a/src/views/progress_bar.rs b/src/views/progress_bar.rs index 44538e4..b0f2bdb 100644 --- a/src/views/progress_bar.rs +++ b/src/views/progress_bar.rs @@ -193,6 +193,8 @@ impl ProgressBar { } impl View for ProgressBar { + view_any!(); + fn draw(&self, printer: &Printer) { // Now, the bar itself... let available = printer.size.x; diff --git a/src/views/radio.rs b/src/views/radio.rs index 15cd4e3..0f5a247 100644 --- a/src/views/radio.rs +++ b/src/views/radio.rs @@ -154,6 +154,9 @@ impl RadioButton { } impl View for RadioButton { + view_any!(); + + fn required_size(&mut self, _: Vec2) -> Vec2 { self.req_size() } diff --git a/src/views/select_view.rs b/src/views/select_view.rs index 4244e9f..be529f6 100644 --- a/src/views/select_view.rs +++ b/src/views/select_view.rs @@ -570,6 +570,9 @@ impl SelectView { } impl View for SelectView { + view_any!(); + + fn draw(&self, printer: &Printer) { self.last_offset.set(printer.offset); diff --git a/src/views/slider_view.rs b/src/views/slider_view.rs index 01476ef..13f7fce 100644 --- a/src/views/slider_view.rs +++ b/src/views/slider_view.rs @@ -112,6 +112,8 @@ impl SliderView { } impl View for SliderView { + view_any!(); + fn draw(&self, printer: &Printer) { match self.orientation { Orientation::Vertical => { diff --git a/src/views/stack_view.rs b/src/views/stack_view.rs index acf5b86..63177dc 100644 --- a/src/views/stack_view.rs +++ b/src/views/stack_view.rs @@ -71,6 +71,8 @@ impl ChildWrapper { // TODO: use macros to make this less ugly? impl View for ChildWrapper { + view_any!(); + fn draw(&self, printer: &Printer) { match *self { ChildWrapper::Shadow(ref v) => v.draw(printer), @@ -322,6 +324,8 @@ impl, I: Iterator> Iterator } impl View for StackView { + view_any!(); + fn draw(&self, printer: &Printer) { let last = self.layers.len(); printer.with_color(ColorStyle::primary(), |printer| { diff --git a/src/views/text_area.rs b/src/views/text_area.rs index 3e72e43..ea0a12c 100644 --- a/src/views/text_area.rs +++ b/src/views/text_area.rs @@ -396,6 +396,8 @@ 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); diff --git a/src/views/text_view.rs b/src/views/text_view.rs index 72c9c75..d175f3f 100644 --- a/src/views/text_view.rs +++ b/src/views/text_view.rs @@ -448,6 +448,8 @@ 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.