#[derive(Copy, Clone, Debug)] /// A cell within a [CellGrid] pub struct Cell { // display coordinates of the cell pub x: f32, pub y: f32, pub width: f32, pub height: f32, // position of the cell in the grid (0-based) pub pos_x: u32, pub pos_y: u32, } /// A grid of equal cells, the grid has a position on the /// display pub struct CellGrid { // display coordinates of the grid x: f32, y: f32, width: f32, height: f32, // size of the grid, in number of cells num_x: u32, num_y: u32, } pub struct CellGridIterator<'a> { grid: &'a CellGrid, // current position when iterating pos_x: u32, pos_y: u32, // current cell when iterating curr: Cell, } impl CellGrid { pub fn new(x: f32, y: f32, width: f32, height: f32, num_x: u32, num_y: u32) -> Self { Self { x, y, width, height, num_x: if num_y > 0 { num_x } else { 0 }, // if one dimension is 0, both shall be 0 num_y: if num_x > 0 { num_y } else { 0 }, // if one dimension is 0, both shall be 0 } } pub fn iter(&self) -> CellGridIterator { CellGridIterator { grid: self, pos_x: 0, pos_y: 0, curr: Cell { x: self.x, y: self.y, width: self.width, height: self.height, pos_x: 0, pos_y: 0, }, } } pub fn rows(&self) -> Self { CellGrid::new(self.x, self.y, self.width, self.height, 1, self.num_y) } pub fn compute_min_height(&self) -> f32 { let mut min_height: f32 = self.height; for cell in self.iter() { min_height = min_height.min(cell.height) } min_height } } impl<'a> CellGridIterator<'a> { fn compute_cell(&mut self) -> () { let grid: &'a CellGrid = self.grid; self.curr.pos_x = self.pos_x; self.curr.pos_y = self.pos_y; let beg_x: f32 = grid.x + (grid.width * self.curr.pos_x as f32) / grid.num_x as f32; let end_x: f32 = grid.x + (grid.width * (self.curr.pos_x + 1) as f32) / grid.num_x as f32; self.curr.x = beg_x.trunc(); self.curr.width = end_x.trunc() - self.curr.x; let beg_y: f32 = grid.y + (grid.height * self.curr.pos_y as f32) / grid.num_y as f32; let end_y: f32 = grid.y + (grid.height * (self.curr.pos_y + 1) as f32) / grid.num_y as f32; self.curr.y = beg_y.trunc(); self.curr.height = end_y.trunc() - self.curr.y; } } impl<'a> Iterator for CellGridIterator<'a> { type Item = Cell; fn next(&mut self) -> Option { if self.pos_y >= self.grid.num_y { None } else { // compute current cell (returned by this call) self.compute_cell(); // advance to next self.pos_x += 1; if self.pos_x >= self.grid.num_x { self.pos_x = 0; self.pos_y += 1; } Some(self.curr) } } }