1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
// Pushrod Rendering Library // Widget Base Definition // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. use crate::render::widget::Widget; use crate::render::widget_cache::WidgetContainer; /// This is an `FnMut` type that takes no additional parameters, returning a mutable reference /// to the current `Widget`, and borrowing the `WidgetContainer` list. pub type FunctionNoParametersType = Option<Box<dyn FnMut(&mut dyn Widget, &[WidgetContainer])>>; /// This is an `FnMut` that takes a `Point` as a `Vec<i32>` of points: X and Y, returning a mutable reference /// to the current `Widget`, and borrowing the `WidgetContainer` list. pub type FunctionPointParametersType = Option<Box<dyn FnMut(&mut dyn Widget, &[WidgetContainer], Vec<i32>)>>; /// This is an `FnMut` that takes a button click ID, the number of clicks, the click state (`true` indicating /// the click was pressed, `false` otherwise), returning a mutable reference /// to the current `Widget`, and borrowing the `WidgetContainer` list. pub type FunctionClickParametersType = Option<Box<dyn FnMut(&mut dyn Widget, &[WidgetContainer], u8, u8, bool)>>; /// This is a registry that contains a series of `FnMut` definitions for actions that can be applied /// to a `Widget`. These can vary from a screen refresh (`tick`), to a mouse move event, etc. Each /// callback gains access to the list of `WidgetContainer` objects stored by the cache. This is /// important in case you wish to modify other `Widget`s on the screen as a result of some action /// that took place. /// /// Keep in mind, however, that you _cannot_ re-borrow your own widget from the `WidgetContainer` /// list, as this will cause a runtime exception. For that, use the top-level `Widget` object that /// was supplied. This will allow you to make changes to the current `Widget` reference, since it /// is an active, `mutable` reference. #[derive(Default)] pub struct CallbackRegistry { /// This is the function that is set when a screen refresh cycle occurs. This function is /// always guaranteed to be called, but there is no guarantee it will call it consistently /// because of the screen refresh rate. If there is a lot of activity on the screen, this /// callback will be called less often. pub on_tick: FunctionNoParametersType, /// This function is called when a mouse enters the scope of a `Widget`. pub on_mouse_entered: FunctionNoParametersType, /// This function is called when a mouse exits the scope of a `Widget`. pub on_mouse_exited: FunctionNoParametersType, /// This function is called when a mouse moves inside the scope of a `Widget`. It contains /// the points as a `Vec<i32>` containing the X and Y coordinates of the position of the mouse /// inside the `Widget`. pub on_mouse_moved: FunctionPointParametersType, /// This function is called when a mouse scroll occurs inside the scope of a `Widget`. It /// contains the points as a `Vec<u8>` indicating the amount of movement either horizontally or /// vertically. pub on_mouse_scrolled: FunctionPointParametersType, /// This function is called when a mouse button is pressed or released. It contains the mouse /// button number, the number of clicks registered, and a boolean flag indicating whether or not /// the mouse button was pressed (`true`) or released (`false`). pub on_mouse_clicked: FunctionClickParametersType, has_on_tick: bool, has_on_mouse_entered: bool, has_on_mouse_exited: bool, has_on_mouse_moved: bool, has_on_mouse_scrolled: bool, has_on_mouse_clicked: bool, } /// Implementation of the `CallbackRegistry`. impl CallbackRegistry { /// Creates a new instance of this object. pub fn new() -> Self { Self { on_tick: None, on_mouse_entered: None, on_mouse_exited: None, on_mouse_moved: None, on_mouse_scrolled: None, on_mouse_clicked: None, has_on_tick: false, has_on_mouse_entered: false, has_on_mouse_exited: false, has_on_mouse_moved: false, has_on_mouse_scrolled: false, has_on_mouse_clicked: false, } } /// Assigns an `FnMut` that will be called when a screen `tick` refresh is performed. If this /// is not set, this function will be bypassed. pub fn on_tick<F>(&mut self, callback: F) where F: FnMut(&mut dyn Widget, &[WidgetContainer]) + 'static, { self.on_tick = Some(Box::new(callback)); self.has_on_tick = true; } /// Assigns an `FnMut` that will be called when the mouse enters the scope of a `Widget`. If this /// is not set, this function will be bypassed. pub fn on_mouse_entered<F>(&mut self, callback: F) where F: FnMut(&mut dyn Widget, &[WidgetContainer]) + 'static, { self.on_mouse_entered = Some(Box::new(callback)); self.has_on_mouse_entered = true; } /// Assigns an `FnMut` that will be called when the mouse exits the scope of a `Widget`. If this /// is not set, this function will be bypassed. pub fn on_mouse_exited<F>(&mut self, callback: F) where F: FnMut(&mut dyn Widget, &[WidgetContainer]) + 'static, { self.on_mouse_exited = Some(Box::new(callback)); self.has_on_mouse_exited = true; } /// Assigns an `FnMut` that will be called when the mouse moves within the scope of a `Widget`. If this /// is not set, this function will be bypassed. pub fn on_mouse_moved<F>(&mut self, callback: F) where F: FnMut(&mut dyn Widget, &[WidgetContainer], Vec<i32>) + 'static, { self.on_mouse_moved = Some(Box::new(callback)); self.has_on_mouse_moved = true; } /// Assigns an `FnMut` that will be called when the mouse scroll occurs within the scope of a /// `Widget`. If this is not set, this function will be bypassed. pub fn on_mouse_scrolled<F>(&mut self, callback: F) where F: FnMut(&mut dyn Widget, &[WidgetContainer], Vec<i32>) + 'static, { self.on_mouse_scrolled = Some(Box::new(callback)); self.has_on_mouse_scrolled = true; } /// Assigns an `FnMut` that will be called when the mouse click occurs within the scope of a /// `Widget`. If this is not set, this function will be bypassed. pub fn on_mouse_clicked<F>(&mut self, callback: F) where F: FnMut(&mut dyn Widget, &[WidgetContainer], u8, u8, bool) + 'static, { self.on_mouse_clicked = Some(Box::new(callback)); self.has_on_mouse_clicked = true; } /// Tells the `Widget` whether or not an `on_tick` callback has been set. pub fn has_on_tick(&mut self) -> bool { self.has_on_tick } /// Tells the `Widget` whether or not an `on_mouse_entered` callback has been set. pub fn has_on_mouse_entered(&mut self) -> bool { self.has_on_mouse_entered } /// Tells the `Widget` whether or not an `on_mouse_exited` callback has been set. pub fn has_on_mouse_exited(&mut self) -> bool { self.has_on_mouse_exited } /// Tells the `Widget` whether or not an `on_mouse_moved` callback has been set. pub fn has_on_mouse_moved(&mut self) -> bool { self.has_on_mouse_moved } /// Tells the `Widget` whether or not an `on_mouse_scrolled` callback has been set. pub fn has_on_mouse_scrolled(&mut self) -> bool { self.has_on_mouse_scrolled } /// Tells the `Widget` whether or not an `on_mouse_clicked` callback has been set. pub fn has_on_mouse_clicked(&mut self) -> bool { self.has_on_mouse_clicked } } pub fn widget_id_for_name(widgets: &[WidgetContainer], name: String) -> usize { match widgets.iter().find(|x| x.get_widget_name() == name.clone()) { Some(x) => x.get_widget_id() as usize, None => 0 as usize, } }