pushrod_widgets/
widget.rs

1// Pushrod Widgets
2// Widget Definition
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use crate::caches::TextureCache;
17use crate::event::PushrodEvent;
18use crate::properties::{WidgetProperties, PROPERTY_INVALIDATED, PROPERTY_HIDDEN};
19use sdl2::render::{Canvas, Texture};
20use sdl2::video::Window;
21
22/// This is the `Widget` trait that all implemented `Widget`s need to extend in order to function
23/// with the `Pushrod` library.  All functions in this trait (aside from default implementations)
24/// should be implemented by the `Widget`.
25pub trait Widget {
26    /// This provides access to the `WidgetProperties` set for a `Widget`.  These must be defined
27    /// in the structure of the `Widget`, as they allow for direct manipulation of the properties.
28    fn properties(&mut self) -> &mut WidgetProperties;
29
30    /// Returns the name of the type of `Widget`.  Must be implemented by `Widget`s, as this helps
31    /// with (de)serialization.
32    fn widget_name(&self) -> String;
33
34    /// Draws the widget.  If you wish to modify the canvas object, you must declare it as `mut` in
35    /// your implementation (ie `fn draw(&mut self, mut canvas: Canvas<Window>)`).  The `_canvas`
36    /// is the currently active drawing canvas at the time this function is called.  This called
37    /// during the draw loop of the `Engine`.  This returns a reference to the stored `Texture` object
38    /// within the `Widget`.  It is then copied to the canvas, and displayed in the display loop.
39    /// In this function, you can just return a reference to the `Texture` if no invalidation state
40    /// was set, otherwise, the draw can be re-performed, and the `Texture` returned.  If the drawing
41    /// function returns no texture, return a `None`, and it will not be rendered during the display
42    /// loop, but it will still be called.  A `TextureCache` is provided in case your `Widget` needs
43    /// to cache an image or a font store.
44    ///
45    /// So, why not just call `draw` each time, if the `Engine` already handles the calling of the
46    /// draw for you when an object needs invalidation?  This is to avoid excess CPU usage.  You
47    /// **can** call the draw method each time: all it will do is return the reference to the already
48    /// drawn `Texture` if you do this.  It's only at the time the contents needs to be redrawn will
49    /// the logic for the draw take place (so long the `invalidated` state is obeyed)
50    fn draw(&mut self, _c: &mut Canvas<Window>, _t: &mut TextureCache) -> Option<&Texture> {
51        None
52    }
53
54    /// Handles a `PushrodEvent` sent to the `Widget` that would also be sent to the application.
55    /// If any `PushrodEvent`s trigger a custom `Widget`-based event, this function can intercept
56    /// the incoming event, and issue one of its own.  If the function returns no events, a
57    /// `None` can be returned, otherwise a `Some(PushrodEvent)` should be returned.  If this
58    /// function returns an event, that event will be sent on to the application as soon as it has
59    /// been generated.
60    fn handle_event(&mut self, _e: PushrodEvent) -> Option<PushrodEvent> {
61        None
62    }
63
64    /// This is called when `PROPERTY_NEEDS_LAYOUT` is enabled in properties.  When a layout is
65    /// required to be built, this function is called, returning the list of `Widget`s that are
66    /// to be added.  If no `Widget`s are to be added, an empty list is valid to return here.
67    /// Otherwise, the list of `Widget`s that this parent `Widget` controls are returned as a
68    /// list here.
69    fn build_layout(&mut self) -> Vec<Box<dyn Widget>> {
70        vec![]
71    }
72
73    /// After a `build_layout` call has been completed, the list of IDs that were added to the display
74    /// list are returned in the same order in from `build_layout`.  The `Widget` that created
75    /// these IDs should then store them here in an array, so that they can be referenced when
76    /// interacted with.
77    fn constructed_layout_ids(&mut self, _ids: Vec<u32>) {}
78
79    /// Set the invalidation key for this `Widget`, indicating that the `TextureCache` needs to
80    /// be redrawn.
81    fn invalidate(&mut self) {
82        self.properties().set_bool(PROPERTY_INVALIDATED);
83    }
84
85    /// Flag indicating whether or not the `draw` method needs to be called for this `Widget` so
86    /// that its `TextureCache` is refreshed.
87    fn invalidated(&mut self) -> bool {
88        self.properties().key_set(PROPERTY_INVALIDATED)
89    }
90
91    /// Sets the `Widget` to hidden state.  If not overridden, this function will only hide the
92    /// current `Widget`, not its children.  To do that, you will need to use the `set_hidden`
93    /// function in `WidgetCache`, which walks the tree.
94    fn hide(&mut self) {
95        self.properties().delete(PROPERTY_HIDDEN);
96    }
97
98    /// Sets the `Widget` to visible state.  If not overridden, this function will only show the
99    /// current `Widget`, not its children.  To do that, you'll need to use the `set_hidden`
100    /// function in `WidgetCache`, which walks the tree.
101    fn show(&mut self) {
102        self.properties().set_bool(PROPERTY_HIDDEN);
103    }
104}