From 30e7bdb817e4a354456ecfe2a5289c6f8e67f618 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Sat, 23 Mar 2024 23:24:06 -0400 Subject: [PATCH] Render the grid of the goban --- otg/gtk/src/components/goban.rs | 108 ++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/otg/gtk/src/components/goban.rs b/otg/gtk/src/components/goban.rs index c7cad2b..3a13c73 100644 --- a/otg/gtk/src/components/goban.rs +++ b/otg/gtk/src/components/goban.rs @@ -44,6 +44,7 @@ use gtk::{ subclass::prelude::*, }; use image::io::Reader as ImageReader; +use otg_core::Color; use std::{cell::RefCell, io::Cursor, rc::Rc}; const WIDTH: i32 = 800; @@ -140,5 +141,112 @@ impl Goban { ctx.set_source_rgb(0.7, 0.7, 0.7); let _ = ctx.paint(); + + let board = self.imp().board_state.borrow(); + + ctx.set_source_rgb(0.1, 0.1, 0.1); + ctx.set_line_width(2.); + let hspace_between = ((width - 40) as f64) / ((board.size.width - 1) as f64); + let vspace_between = ((height - 40) as f64) / ((board.size.height - 1) as f64); + + let pen = Pen { + x_offset: MARGIN as f64, + y_offset: MARGIN as f64, + hspace_between, + vspace_between, + }; + + (0..board.size.width).for_each(|col| { + ctx.move_to( + (MARGIN as f64) + (col as f64) * hspace_between, + MARGIN as f64, + ); + ctx.line_to( + (MARGIN as f64) + (col as f64) * hspace_between, + (height as f64) - (MARGIN as f64), + ); + let _ = ctx.stroke(); + }); + (0..board.size.height).for_each(|row| { + ctx.move_to( + MARGIN as f64, + (MARGIN as f64) + (row as f64) * vspace_between, + ); + ctx.line_to( + (width - MARGIN) as f64, + (MARGIN as f64) + (row as f64) * vspace_between, + ); + let _ = ctx.stroke(); + }); + vec![3, 9, 15].into_iter().for_each(|col| { + vec![3, 9, 15].into_iter().for_each(|row| { + pen.star_point(ctx, col, row); + }); + }); + } +} + +struct Pen { + x_offset: f64, + y_offset: f64, + hspace_between: f64, + vspace_between: f64, +} + +impl Pen { + fn star_point(&self, context: &cairo::Context, row: u8, col: u8) { + context.arc( + self.x_offset + (col as f64) * self.hspace_between, + self.y_offset + (row as f64) * self.vspace_between, + 5., + 0., + 2. * std::f64::consts::PI, + ); + let _ = context.fill(); + } + + fn stone( + &self, + context: &cairo::Context, + row: u8, + col: u8, + color: Color, + liberties: Option, + ) { + match color { + Color::White => context.set_source_rgb(0.9, 0.9, 0.9), + Color::Black => context.set_source_rgb(0.0, 0.0, 0.0), + }; + self.draw_stone(context, row, col); + + if let Some(liberties) = liberties { + let stone_location = self.stone_location(row, col); + context.set_source_rgb(1., 0., 1.); + context.set_font_size(32.); + context.move_to(stone_location.0 - 10., stone_location.1 + 10.); + let _ = context.show_text(&format!("{}", liberties)); + } + } + + fn ghost_stone(&self, context: &cairo::Context, row: u8, col: u8, color: Color) { + match color { + Color::White => context.set_source_rgba(0.9, 0.9, 0.9, 0.5), + Color::Black => context.set_source_rgba(0.0, 0.0, 0.0, 0.5), + }; + self.draw_stone(context, row, col); + } + + fn draw_stone(&self, context: &cairo::Context, row: u8, col: u8) { + let radius = self.hspace_between / 2. - 2.; + let (x_loc, y_loc) = self.stone_location(row, col); + context.arc(x_loc, y_loc, radius, 0.0, 2.0 * std::f64::consts::PI); + let _ = context.fill(); + } + + fn stone_location(&self, row: u8, col: u8) -> (f64, f64) { + ( + self.x_offset + (col as f64) * self.hspace_between, + self.y_offset + (row as f64) * self.vspace_between, + ) } }