use macroquad::prelude::*;
mod cell;
mod position;
pub use position::Position;
pub struct Grid {
width: f32, height: f32, x_offset: position::Position, y_offset: position::Position,
width_cells: usize, height_cells: usize, cell_bg_color: macroquad::color::Color,
gap: f32, gap_color: macroquad::color::Color,
cells: Vec<Vec<cell::Cell>>,
selected_cell: Option<(usize, usize)>, selected_color: Option<macroquad::color::Color>,
}
impl Default for Grid {
fn default() -> Self {
const WIDTH: usize = 10;
const HEIGHT: usize = 10;
Grid {
width: screen_width(),
height: screen_height(),
width_cells: WIDTH,
height_cells: HEIGHT,
cell_bg_color: RED,
gap: 3.0,
gap_color: PINK,
selected_cell: None,
selected_color: Some(BLUE),
cells: (0..HEIGHT)
.into_iter()
.map(|_| {
(0..WIDTH)
.into_iter()
.map(|_| cell::Cell::default())
.collect::<Vec<_>>()
})
.collect(),
x_offset: position::Position::default(),
y_offset: position::Position::default(),
}
}
}
impl Grid {
pub fn set_x_offset(&mut self, x_offset: position::Position) {
self.x_offset = x_offset;
}
pub fn set_y_offset(&mut self, y_offset: position::Position) {
self.y_offset = y_offset;
}
pub fn new(width: f32, height: f32, x_cells: usize, y_cells: usize, gap: f32) -> Self {
const WIDTH: i32 = 10;
const HEIGHT: i32 = 10;
Grid {
width,
height,
width_cells: x_cells,
height_cells: y_cells,
cell_bg_color: RED,
gap,
gap_color: BLACK,
selected_cell: None,
selected_color: Some(BLUE),
cells: (0..HEIGHT)
.into_iter()
.map(|_| {
(0..WIDTH)
.into_iter()
.map(|_| cell::Cell::default())
.collect::<Vec<_>>()
})
.collect(),
x_offset: position::Position::default(),
y_offset: position::Position::default(),
}
}
fn calculate_dimensions(&self) -> (f32, f32) {
let total_x_gap_space = (self.width_cells + 1) as f32 * self.gap;
let total_y_gap_space = (self.height_cells + 1) as f32 * self.gap;
let cell_width = (self.width - total_x_gap_space as f32) / self.width_cells as f32;
let cell_height = (self.height - total_y_gap_space as f32) / self.height_cells as f32;
(cell_width, cell_height)
}
pub fn draw(&self) {
let x_offset = position::as_pixels(self.x_offset, self.width, screen_width());
let y_offset = position::as_pixels(self.y_offset, self.height, screen_height());
draw_rectangle(x_offset, y_offset, self.width, self.height, self.gap_color);
let (cell_width, cell_height) = self.calculate_dimensions();
for i in 0..self.height_cells {
for j in 0..self.width_cells {
self.draw_cell(i, j, cell_width, cell_height, x_offset, y_offset);
}
}
}
fn draw_cell(
&self,
row: usize,
col: usize,
cell_width: f32,
cell_height: f32,
x_offset: f32,
y_offset: f32,
) {
let x_pos = x_offset + self.gap + col as f32 * (cell_width + self.gap as f32);
let y_pos = y_offset + self.gap + row as f32 * (cell_height + self.gap as f32);
let mut color = self.cell_bg_color;
if let Some((selected_row, selected_col)) = self.selected_cell {
if selected_row == row && selected_col == col {
color = self
.selected_color
.expect("there was a selected cell but no selected color");
}
}
else if let Some(set_color) = self.cells[row][col].color {
color = set_color;
}
draw_rectangle(x_pos, y_pos, cell_width, cell_height, color);
if let Some(text) = &self.cells[row][col].text {
let y_pos = y_pos + cell_height;
let text_dim = macroquad::text::measure_text(text, None, cell_height as u16, 1.0); let centered_x = (cell_width - text_dim.width) / 2.0 + x_pos;
let centered_y = y_pos - (cell_height - text_dim.height) / 2.0;
draw_text(text, centered_x, centered_y, cell_height, BLACK);
}
}
pub fn select_cell(&mut self, cell_index: Option<(usize, usize)>) {
self.selected_cell = cell_index;
}
pub fn get_selected_cell_index(&self) -> Option<(usize, usize)> {
self.selected_cell
}
pub fn color_cell(&mut self, row: usize, col: usize, color: macroquad::color::Color) {
self.cells[row][col].color = Some(color);
}
pub fn set_cell_bg_color(&mut self, color: macroquad::color::Color) {
self.cell_bg_color = color;
}
pub fn set_gap_color(&mut self, color: macroquad::color::Color) {
self.gap_color = color;
}
pub fn set_selected_cell_color(&mut self, color: macroquad::color::Color) {
self.selected_color = Some(color);
}
pub fn set_cell_text<T>(&mut self, row: usize, col: usize, text: Option<T>)
where
T: ToString,
{
let t = text.map(|val| val.to_string());
self.cells[row][col].text = t;
}
pub fn set_selected_cell_text<T>(&mut self, text: Option<T>)
where
T: ToString,
{
if let Some( (row, col) ) = self.get_selected_cell_index() {
self.set_cell_text(row, col, text);
}
}
}