diff --git a/kifu/kifu-gtk/src/ui/goban.rs b/kifu/kifu-gtk/src/ui/goban.rs index de38732..8ca10cc 100644 --- a/kifu/kifu-gtk/src/ui/goban.rs +++ b/kifu/kifu-gtk/src/ui/goban.rs @@ -6,11 +6,18 @@ use std::{cell::RefCell, rc::Rc}; const WIDTH: i32 = 800; const HEIGHT: i32 = 800; +#[derive(Clone, Default, PartialEq)] +struct Addr { + row: u8, + column: u8, +} + #[derive(Default)] pub struct GobanPrivate { drawing_area: gtk::DrawingArea, goban: Rc>, + cursor_location: Rc>, } #[glib::object_subclass] @@ -26,6 +33,7 @@ impl ObjectImpl for GobanPrivate { self.drawing_area.set_height_request(HEIGHT); let goban = self.goban.clone(); + let cursor_location = self.cursor_location.clone(); self.drawing_area .set_draw_func(move |_, context, width, height| { let goban = goban.borrow(); @@ -72,7 +80,36 @@ impl ObjectImpl for GobanPrivate { }; }) }); + + let cursor = cursor_location.borrow(); + pen.ghost_stone(context, cursor.row, cursor.column, Color::White); }); + + let motion_controller = gtk::EventControllerMotion::new(); + { + let goban = self.goban.clone(); + let cursor = self.cursor_location.clone(); + let drawing_area = self.drawing_area.clone(); + motion_controller.connect_motion(move |_, x, y| { + let goban = goban.borrow(); + let mut cursor = cursor.borrow_mut(); + let hspace_between = ((WIDTH - 40) as f64) / ((goban.size.width - 1) as f64); + let vspace_between = ((HEIGHT - 40) as f64) / ((goban.size.height - 1) as f64); + + let addr = Addr { + column: ((x.round() - 20.) / hspace_between).round() as u8, + row: ((y.round() - 20.) / vspace_between).round() as u8, + }; + + if *cursor != addr { + println!("redrawing with cursor at {} {}", addr.row, addr.column); + *cursor = addr; + drawing_area.queue_draw(); + } + }); + } + + self.drawing_area.add_controller(motion_controller); } } impl WidgetImpl for GobanPrivate {} @@ -128,4 +165,19 @@ impl Pen { ); let _ = context.fill(); } + + 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), + }; + context.arc( + 20.0 + (col as f64) * self.hspace_between, + 20.0 + (row as f64) * self.vspace_between, + 25.0, + 0.0, + 2.0 * std::f64::consts::PI, + ); + let _ = context.fill(); + } }