Skip to main content

pushrod/widgets/
grid_widget.rs

1// Pushrod Widget Library
2// Grid 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::widget::*;
18use crate::render::widget_cache::WidgetContainer;
19use crate::render::widget_config::*;
20use crate::render::{Points, Size, SIZE_HEIGHT, SIZE_WIDTH};
21
22use sdl2::render::{Canvas, Texture};
23use sdl2::video::Window;
24
25use crate::render::canvas_helper::CanvasHelper;
26use crate::render::layout_cache::LayoutContainer;
27use crate::render::texture_cache::TextureCache;
28use crate::render::texture_store::TextureStore;
29use sdl2::pixels::Color;
30use sdl2::rect::{Point, Rect};
31use std::any::Any;
32use std::collections::HashMap;
33
34/// This is the storage object for the `GridWidget`.  It stores the config, properties, callback registry.
35pub struct GridWidget {
36    config: WidgetConfig,
37    system_properties: HashMap<i32, String>,
38    callback_registry: CallbackRegistry,
39    texture_store: TextureStore,
40    grid_size: u32,
41    grid_connections: bool,
42}
43
44impl CanvasHelper for GridWidget {}
45
46/// This is the implementation of the `GridWidget`, a control that displays a grid inside its bounds.
47impl GridWidget {
48    /// Creates a new `GridWidget` given the `x, y, w, h` coordinates, sets the grid size.
49    pub fn new(points: Points, size: Size, grid_size: u32, grid_connections: bool) -> 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            grid_size,
56            grid_connections,
57        }
58    }
59
60    /// Adjusts the size of the grid, redrawing the object.
61    pub fn set_grid_size(&mut self, grid_size: u32) {
62        self.grid_size = grid_size;
63        self.get_config().set_invalidated(true);
64    }
65
66    /// Turns on or off the grid, showing a grid or dots.
67    pub fn set_grid_connections(&mut self, grid_connections: bool) {
68        self.grid_connections = grid_connections;
69        self.get_config().set_invalidated(true);
70    }
71}
72
73/// This is the `Widget` implementation of the `GridWidget`.
74impl Widget for GridWidget {
75    /// Draws the `GridWidget` contents.
76    fn draw(&mut self, c: &mut Canvas<Window>, _t: &mut TextureCache) -> Option<&Texture> {
77        if self.get_config().invalidated() {
78            let bounds = self.get_config().get_size(CONFIG_SIZE);
79
80            self.texture_store
81                .create_or_resize_texture(c, bounds[0] as u32, bounds[1] as u32);
82
83            let base_color = self.get_color(CONFIG_COLOR_BASE);
84            let border_color = self.get_config().get_color(CONFIG_COLOR_BORDER);
85            let size = self.get_config().get_size(CONFIG_SIZE);
86            let grid_connections = self.grid_connections;
87            let grid_size = self.grid_size as usize;
88
89            c.with_texture_canvas(self.texture_store.get_mut_ref(), |texture| {
90                texture.set_draw_color(base_color);
91                texture.clear();
92
93                if grid_connections {
94                    texture.set_draw_color(Color::RGB(192, 192, 192));
95
96                    for i in (0..size[SIZE_WIDTH]).step_by(grid_size) {
97                        texture
98                            .draw_line(
99                                Point::new(i as i32, 0),
100                                Point::new(i as i32, size[SIZE_HEIGHT] as i32),
101                            )
102                            .unwrap();
103                    }
104
105                    for i in (0..size[SIZE_HEIGHT]).step_by(grid_size) {
106                        texture
107                            .draw_line(
108                                Point::new(0, i as i32),
109                                Point::new(size[SIZE_WIDTH] as i32, i as i32),
110                            )
111                            .unwrap();
112                    }
113                } else {
114                    texture.set_draw_color(Color::RGB(0, 0, 0));
115
116                    for x in (0..size[SIZE_WIDTH]).step_by(grid_size) {
117                        for y in (0..size[SIZE_HEIGHT]).step_by(grid_size) {
118                            texture.draw_point(Point::new(x as i32, y as i32)).unwrap();
119                        }
120                    }
121                }
122
123                texture.set_draw_color(border_color);
124                texture
125                    .draw_rect(Rect::new(0, 0, size[0], size[1]))
126                    .unwrap();
127            })
128            .unwrap();
129        }
130
131        self.texture_store.get_optional_ref()
132    }
133
134    default_widget_functions!();
135    default_widget_properties!();
136    default_widget_callbacks!();
137}