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}