pushrod/widgets/
progress_widget.rs

1// Pushrod Widget Library
2// Progress Widget
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::callbacks::CallbackRegistry;
17use crate::render::layout_cache::LayoutContainer;
18use crate::render::widget::*;
19use crate::render::widget_cache::WidgetContainer;
20use crate::render::widget_config::*;
21use crate::render::{Points, Size};
22
23use sdl2::pixels::Color;
24use sdl2::rect::Rect;
25use sdl2::video::Window;
26
27use crate::render::texture_cache::TextureCache;
28use crate::render::texture_store::TextureStore;
29use sdl2::render::{Canvas, Texture};
30use std::any::Any;
31use std::collections::HashMap;
32
33/// This is the storage object for the `ProgressWidget`.  It stores the config, properties, callback registry,
34/// the base widget, and progress from 0 to 100.
35pub struct ProgressWidget {
36    config: WidgetConfig,
37    system_properties: HashMap<i32, String>,
38    callback_registry: CallbackRegistry,
39    texture_store: TextureStore,
40    progress: u8,
41}
42
43/// Creates a new `ProgressWidget`, which draws a progress bar inside a `BaseWidget`.
44impl ProgressWidget {
45    /// Creates a new instance of the `ProgressWidget` object.  It draws a progress bar-style
46    /// `Widget` given the `xywh` coordinates, and the `percentage` of fill from 0-100.  The
47    /// base color and border colors are set to white and black, respectively.  Use the
48    /// `COLOR_SECONDARY` setting to change the color of the fill for the progress bar.
49    pub fn new(points: Points, size: Size, progress: u8) -> Self {
50        Self {
51            config: WidgetConfig::new(points, size),
52            system_properties: HashMap::new(),
53            callback_registry: CallbackRegistry::new(),
54            texture_store: TextureStore::default(),
55            progress,
56        }
57    }
58
59    /// Sets the progress for the widget.  Progress value is between 0 and 100.  Anything over
60    /// 100 will just set the progress to 100.
61    pub fn set_progress(&mut self, progress: u8) {
62        if progress > 100 {
63            self.progress = 100;
64        } else {
65            self.progress = progress;
66        }
67
68        self.get_config().set_invalidated(true);
69    }
70
71    /// Retrieves the current progress value as a `u8` value.
72    pub fn get_progress(&mut self) -> u8 {
73        self.progress
74    }
75}
76
77/// This is the `Widget` implementation of the `ProgressWidget`.  It contains a `BaseWidget` within
78/// its bounds to draw the base background, then draws the progress fill over the top.
79impl Widget for ProgressWidget {
80    fn draw(&mut self, c: &mut Canvas<Window>, _t: &mut TextureCache) -> Option<&Texture> {
81        if self.get_config().invalidated() {
82            let bounds = self.get_config().get_size(CONFIG_SIZE);
83
84            self.texture_store
85                .create_or_resize_texture(c, bounds[0] as u32, bounds[1] as u32);
86
87            let base_color = self.get_color(CONFIG_COLOR_SECONDARY);
88            let progress_width = (f64::from(self.get_size(CONFIG_SIZE)[0])
89                * (f64::from(self.progress))
90                / 100.0) as u32;
91            let progress_height = self.get_size(CONFIG_SIZE)[1] - 2;
92            let border_color = self.get_config().get_color(CONFIG_COLOR_BORDER);
93            let bounds = self.get_config().get_size(CONFIG_SIZE);
94
95            c.with_texture_canvas(self.texture_store.get_mut_ref(), |texture| {
96                texture.set_draw_color(Color::RGB(255, 255, 255));
97                texture.clear();
98
99                texture.set_draw_color(base_color);
100                texture
101                    .fill_rect(Rect::new(1, 1, progress_width, progress_height))
102                    .unwrap();
103
104                texture.set_draw_color(border_color);
105                texture
106                    .draw_rect(Rect::new(0, 0, bounds[0], bounds[1]))
107                    .unwrap();
108            })
109            .unwrap();
110        }
111
112        self.texture_store.get_optional_ref()
113    }
114
115    default_widget_functions!();
116    default_widget_properties!();
117    default_widget_callbacks!();
118}