pushrod/render/widget_config.rs
1// Pushrod Rendering Library
2// Widget Configuration Store
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::render::{Points, Size};
17use sdl2::pixels::Color;
18use std::collections::HashMap;
19
20/// `Widget` Base `Color` key for `colors` `HashMap`. This is the base fill color of a `Widget`
21/// that is in an unselected state. This stored as a `Config::Color`.
22pub const CONFIG_COLOR_BASE: u8 = 0;
23
24/// `Widget` Hover `Color` key for `colors` `HashMap`. This is the base fill color of a `Widget`
25/// that has a mouse hovering over the top of the `Widget`, or when a `mouse_entered` event is
26/// triggered. This is optional; the `Widget` does not need to honor this color if it does not
27/// support a hover state. This stored as a `Config::Color`.
28pub const CONFIG_COLOR_HOVER: u8 = 1;
29
30/// `Widget` Border `Color` key for `colors` `HashMap`. This should be used for the color of the
31/// border, if the `Widget` draws a border. This stored as a `Config::Color`.
32pub const CONFIG_COLOR_BORDER: u8 = 2;
33
34/// `Widget` Text `Color` key for `colors` `HashMap`. This should be the color for the text being
35/// displayed inside the `Widget`. This stored as a `Config::Color`.
36pub const CONFIG_COLOR_TEXT: u8 = 3;
37
38/// `Widget` Selected `Color` key for `colors` `HashMap`. This is the color the `Widget` should
39/// display when in selected state. This stored as a `Config::Color`.
40pub const CONFIG_COLOR_SELECTED: u8 = 4;
41
42/// `Widget` Secondary `Color` key for `colors` `HashMap`. This is the color the `Widget` should
43/// display for any secondary properties, such as a fill color for a progress widget, a spinner,
44/// etc. This stored as a `Config::Color`.
45pub const CONFIG_COLOR_SECONDARY: u8 = 5;
46
47/// `Widget` configuration to store its origin on the screen. This is a `Config::Points` object in the
48/// config.
49pub const CONFIG_ORIGIN: u8 = 6;
50
51/// `Widget` configuration that stores the size of the `Widget`. This is a `Config::Size` object
52/// in the config.
53pub const CONFIG_SIZE: u8 = 7;
54
55/// `Widget` configuration that stores the display border in pixels. This is stored as a
56/// `Config::Numeric` value.
57pub const CONFIG_BORDER_WIDTH: u8 = 8;
58
59/// `Widget` text store, used to display text on the screen. This is stored as a `Config::Text`
60/// value.
61pub const CONFIG_TEXT: u8 = 9;
62
63/// `Widget` image position direction, controls the position of an `Image` within the bounds of a
64/// `Widget`. This is stored as a `Config::CompassPosition` value.
65pub const CONFIG_IMAGE_POSITION: u8 = 11;
66
67/// `TextWidget` font size control. This is stored as a `Config::Numeric` value.
68pub const CONFIG_FONT_SIZE: u8 = 12;
69
70/// `PushButtonWidget` selected state. This is stored as a `Config::Toggle` value.
71pub const CONFIG_SELECTED_STATE: u8 = 13;
72
73/// This enum is used by the `ImageWidget`, which controls the positioning of the image being
74/// rendered within the bounds of the `Widget`.
75#[derive(Clone, Debug, Copy)]
76pub enum CompassPosition {
77 /// Upper left-hand corner of the bounds.
78 NW,
79
80 /// Centered top of the bounds.
81 N,
82
83 /// Upper right-hand corner of the bounds.
84 NE,
85
86 /// Centered left side of the bounds.
87 W,
88
89 /// Center of the bounds.
90 Center,
91
92 /// Centered right side of the bounds.
93 E,
94
95 /// Lower left-hand corner of the bounds.
96 SW,
97
98 /// Bottom center of the bounds.
99 S,
100
101 /// Lower right-hand corner of the bounds.
102 SE,
103}
104
105/// This struct stores padding constraints.
106#[derive(Clone, Default, Debug, Copy)]
107pub struct PaddingConstraint {
108 pub top: i32,
109 pub bottom: i32,
110 pub left: i32,
111 pub right: i32,
112 pub spacing: i32,
113}
114
115/// Implementation to create a new `PaddingConstraint` object.
116impl PaddingConstraint {
117 pub fn new(top: i32, bottom: i32, left: i32, right: i32, spacing: i32) -> Self {
118 Self {
119 top,
120 bottom,
121 left,
122 right,
123 spacing,
124 }
125 }
126}
127
128/// Configuration object type - allows configurations to be set using `Piston`, `Pushrod`, or
129/// native types.
130#[derive(Clone, Debug)]
131pub enum Config {
132 /// This stores a `Points` type.
133 Points(Points),
134
135 /// This stores a `Size` type.
136 Size(Size),
137
138 /// This stores a `Color`.
139 Color(Color),
140
141 /// This stores a numeric value in the form of an `i32` value.
142 Numeric(i32),
143
144 /// This stores a `String` of text.
145 Text(String),
146
147 /// This stores a `true`/`false` boolean flag.
148 Toggle(bool),
149
150 /// This stores a `ComapssPosition`.
151 CompassPosition(CompassPosition),
152
153 /// This stores a `PaddingConstraint`.
154 PaddingConstraint(PaddingConstraint),
155}
156
157/// This is the store for the `WidgetConfig`, which each `Widget` object needs. This stores
158/// information about the `Widget`. It currently contains the point of origin, size, a `HashMap` of
159/// different `Color`s, a border width, and an invalidation flag.
160pub struct WidgetConfig {
161 /// The `HashMap` store for configuration objects.
162 pub config: HashMap<u8, Config>,
163
164 /// `Widget`'s hidden flag - any children that refer to this object as a `parent_id` will not
165 /// be drawn, and their events will not be received.
166 hidden: bool,
167
168 /// `Widget`'s enabled flag - any mouse events are ignored, but drawing is still performed.
169 enabled: bool,
170
171 /// `Widget`'s redraw flag. Set `true` if the object needs to be redrawn, `false` otherwise.
172 invalidated: bool,
173}
174
175/// This is the implementation of the `WidgetConfig`.
176impl WidgetConfig {
177 /// Constructor - takes the X, Y, W, and H coordinates of the `Widget`, physically in the
178 /// main `Canvas`.
179 pub fn new(points: Points, size: Size) -> Self {
180 Self {
181 config: [
182 (CONFIG_ORIGIN, Config::Points(points)),
183 (CONFIG_SIZE, Config::Size(size)),
184 (CONFIG_COLOR_BASE, Config::Color(Color::RGB(255, 255, 255))),
185 (CONFIG_BORDER_WIDTH, Config::Numeric(0)),
186 ]
187 .iter()
188 .cloned()
189 .collect(),
190 hidden: false,
191 enabled: true,
192 invalidated: true,
193 }
194 }
195
196 /// Converts an X point to the physical X point on the `Canvas` plus the point of origin.
197 /// Returns `i32` containing the modified X coordinate. This is a convenience method for the
198 /// `Widget` to draw based on a 0x0 point of origin.
199 pub fn to_x(&self, x: i32) -> i32 {
200 self.get_point(CONFIG_ORIGIN)[0] + x
201 }
202
203 /// Converts a Y point to the physical Y point on the `Canvas` plus the point of origin.
204 /// Returns `i32` containing the modified Y coordinate. This is a convenience method for the
205 /// `Widget` to draw based on a 0x0 point of origin.
206 pub fn to_y(&self, y: i32) -> i32 {
207 self.get_point(CONFIG_ORIGIN)[1] + y
208 }
209
210 /// Sets the invalidation state of the `Widget`, telling the `Engine` that the `Widget`
211 /// contents has changed, and must be redrawn. Setting the `flag` to `true` indicates that
212 /// the `Widget` needs to be redrawn on the screen, `false` indicates that it its state has
213 /// not changed, and its image can be pulled from a buffer if necessary, skipping the `draw`
214 /// call.
215 pub fn set_invalidated(&mut self, flag: bool) {
216 self.invalidated = flag;
217 }
218
219 /// Returns the `invalidation` state. Returns a `bool` containing the state.
220 pub fn invalidated(&self) -> bool {
221 self.invalidated
222 }
223
224 /// Enables the `Widget` for interaction.
225 pub fn enable(&mut self) {
226 self.enabled = true;
227 self.invalidated = true;
228 }
229
230 /// Disables the `Widget`, preventing interaction.
231 pub fn disable(&mut self) {
232 self.enabled = false;
233 self.invalidated = true;
234 }
235
236 /// Indicates whether or not this `Widget` is enabled or disabled - `true` if enabled,
237 /// `false` otherwise.
238 pub fn is_enabled(&self) -> bool {
239 self.enabled
240 }
241
242 /// Prevents the `Widget` from being drawn on the screen, or being interacted with. No events
243 /// are received by this `Widget` when hidden.
244 pub fn hide(&mut self) {
245 self.hidden = true;
246 self.invalidated = true;
247 }
248
249 /// Displays the `Widget` on the screen.
250 pub fn show(&mut self) {
251 self.hidden = false;
252 self.invalidated = true;
253 }
254
255 /// Indicates whether or not this `Widget` has been hidden from view - `true` if this `Widget`
256 /// is hidden, `false` otherwise.
257 pub fn is_hidden(&self) -> bool {
258 self.hidden
259 }
260
261 /// Sets a point for a configuration key.
262 pub fn set_point(&mut self, config: u8, x: i32, y: i32) {
263 self.config.insert(config, Config::Points(vec![x, y]));
264 }
265
266 /// Sets a size for a configuration key.
267 pub fn set_size(&mut self, config: u8, w: u32, h: u32) {
268 self.config.insert(config, Config::Size(vec![w, h]));
269 }
270
271 /// Sets a color for a configuration key.
272 pub fn set_color(&mut self, config: u8, color: Color) {
273 self.config.insert(config, Config::Color(color));
274 }
275
276 /// Sets a numeric value for a configuration key.
277 pub fn set_numeric(&mut self, config: u8, value: i32) {
278 self.config.insert(config, Config::Numeric(value));
279 }
280
281 /// Sets a text value for a configuration key.
282 pub fn set_text(&mut self, config: u8, text: String) {
283 self.config.insert(config, Config::Text(text));
284 }
285
286 /// Sets a toggle for a configuration key.
287 pub fn set_toggle(&mut self, config: u8, flag: bool) {
288 self.config.insert(config, Config::Toggle(flag));
289 }
290
291 /// Sets a compass position for a configuration key.
292 pub fn set_compass(&mut self, config: u8, value: CompassPosition) {
293 self.config.insert(config, Config::CompassPosition(value));
294 }
295
296 /// Applies a `PaddingConstraint`.
297 pub fn set_padding(&mut self, config: u8, value: PaddingConstraint) {
298 self.config.insert(config, Config::PaddingConstraint(value));
299 }
300
301 /// Retrieves a `Points` for a configuration key. Returns `Points::default` if not set.
302 pub fn get_point(&self, k: u8) -> Points {
303 match self.config.get(&k) {
304 Some(Config::Points(point)) => point.clone(),
305 _ => Points::default(),
306 }
307 }
308
309 /// Retrieves a `Size` for a configuration key. Returns a `Size::default` if not set.
310 pub fn get_size(&self, k: u8) -> Size {
311 match self.config.get(&k) {
312 Some(Config::Size(size)) => size.clone(),
313 _ => Size::default(),
314 }
315 }
316
317 /// Retrieves a `Color` for a configuration key. Returns white if not set.
318 pub fn get_color(&self, k: u8) -> Color {
319 match self.config.get(&k) {
320 Some(Config::Color(color)) => *color,
321 _ => Color::RGB(255, 255, 255),
322 }
323 }
324
325 /// Retrieves a numeric value for a configuration key. Returns 0 if not set.
326 pub fn get_numeric(&self, k: u8) -> i32 {
327 match self.config.get(&k) {
328 Some(Config::Numeric(numeric)) => *numeric,
329 _ => 0,
330 }
331 }
332
333 /// Retrieves text for a configuration key. Returns a blank string if not set.
334 pub fn get_text(&self, k: u8) -> String {
335 match self.config.get(&k) {
336 Some(Config::Text(text)) => text.clone(),
337 _ => String::from(""),
338 }
339 }
340
341 /// Retrieves a boolean toggle for a configuration key. Returns `false` if not set.
342 pub fn get_toggle(&self, k: u8) -> bool {
343 match self.config.get(&k) {
344 Some(Config::Toggle(toggle)) => *toggle,
345 _ => false,
346 }
347 }
348
349 /// Retrieves a `CompassPosition` toggle for a configuration key. Returns `CompassPosition::W` if not set.
350 pub fn get_compass(&self, k: u8) -> CompassPosition {
351 match self.config.get(&k) {
352 Some(Config::CompassPosition(position)) => *position,
353 _ => CompassPosition::W,
354 }
355 }
356
357 /// Retrieves a `PaddingConstraint` toggle for a configuration key. Returns empty `PaddingConstraint` if not set.
358 pub fn get_padding(&self, k: u8) -> PaddingConstraint {
359 match self.config.get(&k) {
360 Some(Config::PaddingConstraint(constraint)) => *constraint,
361 _ => PaddingConstraint::default(),
362 }
363 }
364}