cursive_core/view/
view_trait.rs

1use crate::direction::Direction;
2use crate::event::{AnyCb, Event, EventResult};
3use crate::rect::Rect;
4use crate::view::{AnyView, Selector};
5use crate::Printer;
6use crate::Vec2;
7use std::any::Any;
8
9/// Error indicating a view was not found.
10#[derive(Debug)]
11pub struct ViewNotFound;
12
13/// Error indicating a view could not take focus.
14#[derive(Debug)]
15pub struct CannotFocus;
16
17impl std::fmt::Display for ViewNotFound {
18    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
19        write!(f, "View could not be found")
20    }
21}
22
23impl std::fmt::Display for CannotFocus {
24    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
25        write!(f, "View does not take focus")
26    }
27}
28
29impl std::error::Error for ViewNotFound {}
30
31/// Main trait defining a view behaviour.
32///
33/// This is what you should implement to define a custom View.
34pub trait View: Any + AnyView + Send + Sync {
35    /// Draws the view with the given printer (includes bounds) and focus.
36    ///
37    /// This is the only *required* method to implement.
38    fn draw(&self, printer: &Printer);
39
40    /// Called once the size for this view has been decided.
41    ///
42    /// It can be used to pre-compute the configuration of child views.
43    ///
44    /// View groups should propagate the information to their children.
45    ///
46    /// At this point, the given size is final and cannot be negotiated.
47    /// It is guaranteed to be the size available for the call to `draw()`.
48    fn layout(&mut self, _: Vec2) {}
49
50    /// Should return `true` if the view content changed since the last call
51    /// to `layout()`.
52    ///
53    /// This is mostly an optimisation for views where the layout phase is
54    /// expensive.
55    ///
56    /// * Views can ignore it and always return true (default implementation).
57    ///   They will always be assumed to have changed.
58    /// * View Groups can ignore it and always re-layout their children.
59    ///     * If they call `required_size` or `layout` with stable parameters,
60    ///       the children may cache the result themselves and speed up the
61    ///       process anyway.
62    fn needs_relayout(&self) -> bool {
63        true
64    }
65
66    /// Returns the minimum size the view requires with the given restrictions.
67    ///
68    /// This is the main way a view communicate its size to its parent.
69    ///
70    /// Some views have a fixed size, and will ignore the `constraint`
71    /// parameter entirely.
72    ///
73    /// Some views are flexible, and may adapt fully or partially to the
74    /// constraints.
75    ///
76    /// Default implementation always return `(1,1)`.
77    fn required_size(&mut self, constraint: Vec2) -> Vec2 {
78        let _ = constraint;
79        Vec2::new(1, 1)
80    }
81
82    /// Called when an event is received (key press, mouse event, ...).
83    ///
84    /// You can return an `EventResult`:
85    /// * `EventResult::Ignored` means the event was not processed and may be
86    ///    sent to another view.
87    /// * `EventResult::Consumed` means the event was consumed and should not
88    ///    be sent to any other view. It may in addition include a callback
89    ///    to be run.
90    ///
91    /// The default implementation just ignores any event.
92    fn on_event(&mut self, _: Event) -> EventResult {
93        EventResult::Ignored
94    }
95
96    /// Runs a closure on the view identified by the given selector.
97    ///
98    /// See [`Finder::call_on`] for a nicer interface, implemented for all
99    /// views.
100    ///
101    /// [`Finder::call_on`]: crate::view::Finder::call_on
102    ///
103    /// If the selector doesn't find a match, the closure will not be run.
104    ///
105    /// View groups should implement this to forward the call to each children.
106    ///
107    /// Default implementation is a no-op.
108    fn call_on_any(&mut self, _: &Selector, _: AnyCb) {}
109
110    /// Moves the focus to the view identified by the given selector.
111    ///
112    /// Returns `Ok(_)` if the view was found and selected.
113    /// A callback may be included, it should be run on `&mut Cursive`.
114    ///
115    /// Default implementation simply returns `Err(ViewNotFound)`.
116    fn focus_view(&mut self, _: &Selector) -> Result<EventResult, ViewNotFound> {
117        Err(ViewNotFound)
118    }
119
120    /// Attempt to give this view the focus.
121    ///
122    /// `source` indicates where the focus comes from.
123    /// When the source is unclear (for example mouse events),
124    /// `Direction::none()` can be used.
125    ///
126    /// Returns `Ok(_)` if the focus was taken.
127    /// Returns `Err(_)` if this view does not take focus (default implementation).
128    fn take_focus(&mut self, source: Direction) -> Result<EventResult, CannotFocus> {
129        let _ = source;
130
131        Err(CannotFocus)
132    }
133
134    /// What part of the view is important and should be visible?
135    ///
136    /// When only part of this view can be visible, this helps
137    /// determine which part.
138    ///
139    /// It is given the view size (same size given to `layout`).
140    ///
141    /// Default implementation return the entire view.
142    fn important_area(&self, view_size: Vec2) -> Rect {
143        Rect::from_size((0, 0), view_size)
144    }
145
146    /// Returns the type of this view.
147    ///
148    /// Useful when you have a `&dyn View`.
149    ///
150    /// View implementation don't usually have to override this.
151    fn type_name(&self) -> &'static str {
152        std::any::type_name::<Self>()
153    }
154}
155
156impl dyn View {
157    /// Attempts to downcast `self` to a concrete type.
158    pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
159        self.as_any().downcast_ref()
160    }
161
162    /// Attempts to downcast `self` to a concrete type.
163    pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
164        self.as_any_mut().downcast_mut()
165    }
166
167    /// Attempts to downcast `Box<Self>` to a concrete type.
168    pub fn downcast<T: Any>(self: Box<Self>) -> Result<Box<T>, Box<Self>> {
169        // Do the check here + unwrap, so the error
170        // value is `Self` and not `dyn Any`.
171        if self.as_any().is::<T>() {
172            Ok(self.as_boxed_any().downcast().unwrap())
173        } else {
174            Err(self)
175        }
176    }
177
178    /// Checks if this view is of type `T`.
179    pub fn is<T: Any>(&self) -> bool {
180        self.as_any().is::<T>()
181    }
182}