//! Gameboard view. use graphics::character::CharacterCache; use graphics::types::Color; use graphics::{Context, Graphics}; use crate::gameboard_controller::GameboardController; pub struct GameboardViewSettings { pub position: [f64; 2], pub size: f64, pub background_color: Color, pub border_color: Color, pub board_edge_color: Color, pub section_edge_color: Color, pub cell_edge_color: Color, pub board_edge_radius: f64, pub section_edge_radius: f64, pub cell_edge_radius: f64, pub selected_cell_background_color: Color, pub text_color: Color, pub loaded_cell_background_color: Color, pub invalid_cell_background_color: Color, pub invalid_selected_cell_background_color: Color, pub completed_background_color: Color, } impl GameboardViewSettings { pub fn new() -> GameboardViewSettings { GameboardViewSettings { position: [10.0; 2], size: 400.0, background_color: [0.8, 0.8, 1.0, 1.0], border_color: [0.0, 0.0, 0.2, 1.0], board_edge_color: [0.0, 0.0, 0.2, 1.0], section_edge_color: [0.0, 0.0, 0.2, 1.0], cell_edge_color: [0.0, 0.0, 0.2, 1.0], board_edge_radius: 3.0, section_edge_radius: 2.0, cell_edge_radius: 1.0, selected_cell_background_color: [0.9, 0.9, 1.0, 1.0], text_color: [0.0, 0.0, 0.1, 1.0], loaded_cell_background_color: [1.0, 1.0, 1.0, 1.0], invalid_cell_background_color: [1.0, 0.0, 0.0, 1.0], invalid_selected_cell_background_color: [1.0, 0.0, 0.5, 1.0], completed_background_color: [0.0, 1.0, 0.0, 1.0], } } } pub struct GameboardView { pub settings: GameboardViewSettings, } impl GameboardView { pub fn new(settings: GameboardViewSettings) -> GameboardView { GameboardView { settings: settings } } pub fn draw( &self, controller: &GameboardController, glyphs: &mut C, c: &Context, g: &mut G, ) where C: CharacterCache, { use graphics::{Image, Line, Rectangle, Transformed}; let ref settings = self.settings; let board_rect = [ settings.position[0], settings.position[1], settings.size, settings.size, ]; if controller.gameboard.completed { Rectangle::new(settings.completed_background_color).draw( board_rect, &c.draw_state, c.transform, g, ); } else { Rectangle::new(settings.background_color).draw( board_rect, &c.draw_state, c.transform, g, ); for i in 0..9 { for j in 0..9 { if controller.gameboard.cells[i][j].loaded { color_cell( settings, [j, i], settings.loaded_cell_background_color, c, g, ); } else if controller.gameboard.cells[i][j].invalid { color_cell( settings, [j, i], settings.invalid_cell_background_color, c, g, ); } } } if let Some(ind) = controller.selected_cell { let cell = controller.gameboard.cells[ind[1]][ind[0]]; let color = if !cell.loaded { if !cell.invalid { settings.selected_cell_background_color } else { settings.invalid_selected_cell_background_color } } else { settings.loaded_cell_background_color }; color_cell(settings, ind, color, c, g); } } let text_image = Image::new_color(settings.text_color); let cell_size = settings.size / 9.0; for j in 0..9 { for i in 0..9 { if let Some(ch) = controller.gameboard.char([i, j]) { let pos = [ settings.position[0] + i as f64 * cell_size + 15.0, settings.position[1] + j as f64 * cell_size + 34.0, ]; if let Ok(character) = glyphs.character(34, ch) { let ch_x = pos[0] + character.left(); let ch_y = pos[1] - character.top(); let text_image = text_image.src_rect([ character.atlas_offset[0], character.atlas_offset[1], character.atlas_size[0], character.atlas_size[1], ]); text_image.draw( character.texture, &c.draw_state, c.transform.trans(ch_x, ch_y), g, ); } } } } let cell_edge = Line::new(settings.cell_edge_color, settings.cell_edge_radius); let section_edge = Line::new(settings.section_edge_color, settings.section_edge_radius); for i in 0..9 { let x = settings.position[0] + i as f64 / 9.0 * settings.size; let y = settings.position[1] + i as f64 / 9.0 * settings.size; let x2 = settings.position[0] + settings.size; let y2 = settings.position[1] + settings.size; let vline = [x, settings.position[1], x, y2]; let hline = [settings.position[0], y, x2, y]; if (i % 3) == 0 { section_edge.draw(vline, &c.draw_state, c.transform, g); section_edge.draw(hline, &c.draw_state, c.transform, g); } else { cell_edge.draw(vline, &c.draw_state, c.transform, g); cell_edge.draw(hline, &c.draw_state, c.transform, g); } } Rectangle::new_border(settings.board_edge_color, settings.board_edge_radius).draw( board_rect, &c.draw_state, c.transform, g, ); } } fn color_cell( settings: &GameboardViewSettings, ind: [usize; 2], color: [f32; 4], c: &Context, g: &mut G, ) { use graphics::Rectangle; let cell_size = settings.size / 9.0; let pos = [ind[0] as f64 * cell_size, ind[1] as f64 * cell_size]; let cell_rect = [ settings.position[0] + pos[0], settings.position[1] + pos[1], cell_size, cell_size, ]; Rectangle::new(color).draw(cell_rect, &c.draw_state, c.transform, g); }