diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/gui.rs | 108 |
1 files changed, 56 insertions, 52 deletions
@@ -16,32 +16,35 @@ */ use fltk::{app::*, button::*, draw::*, menu::*, text::*, window::*}; +use std::rc::*; use crate::game::*; -struct BoardRendererBackend { +struct BoardRendererDetails { xorg: i32, yorg: i32, square_size: i32, } -impl BoardRendererBackend { - fn initialise(frame: &Button, frame_pad: i32, game_size: i32) -> BoardRendererBackend { - let x0 = frame.x(); - let y0 = frame.y(); - let xorg = x0 + frame_pad; - let yorg = y0 + frame_pad; - let board_size = i32::min(frame.width(), frame.height()) - frame_pad * 2; - - BoardRendererBackend { - xorg, - yorg, - square_size: board_size / game_size, +impl BoardRendererDetails { + fn default() -> BoardRendererDetails { + BoardRendererDetails { + xorg: 0, + yorg: 0, + square_size: 0, } } + + fn set(&mut self, button: &Button, frame_pad: i32, game_size: i32) { + let x0 = button.x(); + let y0 = button.y(); + self.xorg = x0 + frame_pad; + self.yorg = y0 + frame_pad; + let board_size = i32::min(button.width(), button.height()) - frame_pad * 2; + self.square_size = board_size / game_size; + } } -#[derive(Clone, Copy)] struct BoardRenderer { even_square_colour: Color, odd_square_colour: Color, @@ -75,7 +78,7 @@ impl BoardRenderer { fn render_stone( &self, - backend: &BoardRendererBackend, + details: &BoardRendererDetails, player: Player, stone: Stone, row: i32, @@ -88,11 +91,11 @@ impl BoardRenderer { }); // Gap scales with square size - let stone_gap = (backend.square_size as f32 * (1.00 - self.stone_size)).round() as i32; - let d = backend.square_size - stone_gap * 2; + let stone_gap = (details.square_size as f32 * (1.00 - self.stone_size)).round() as i32; + let d = details.square_size - stone_gap * 2; let shift = (shift * d) / 8; - let x1 = backend.xorg + col * backend.square_size + stone_gap + shift; - let y1 = backend.yorg + row * backend.square_size + stone_gap - shift; + let x1 = details.xorg + col * details.square_size + stone_gap + shift; + let y1 = details.yorg + row * details.square_size + stone_gap - shift; // Outline with thickness varying by stone size let setup_border_pen = || { @@ -146,19 +149,19 @@ impl BoardRenderer { fn render_icons( &self, - backend: &BoardRendererBackend, + details: &BoardRendererDetails, player: Player, row: i32, col: i32, shift: i32, ) { - let stone_gap = backend.square_size as f32 * (1.00 - self.stone_size); + let stone_gap = details.square_size as f32 * (1.00 - self.stone_size); let icon_gap = (stone_gap * 0.15).round() as i32; let icon_width = (stone_gap * 0.7).round() as i32; let icon_height = icon_width / 2; - let x1 = backend.xorg + col * backend.square_size + icon_gap; - let y1 = backend.yorg + (row + 1) * backend.square_size - icon_gap; + let x1 = details.xorg + col * details.square_size + icon_gap; + let y1 = details.yorg + (row + 1) * details.square_size - icon_gap; set_line_style(LineStyle::Solid, i32::max(1, icon_width / 8)); set_draw_color(Color::Black); @@ -174,17 +177,17 @@ impl BoardRenderer { set_line_style(LineStyle::Solid, 1); } - fn render_stack(&self, backend: &BoardRendererBackend, row: i32, col: i32, stack: &Stack) { + fn render_stack(&self, details: &BoardRendererDetails, row: i32, col: i32, stack: &Stack) { // Is there a better way than usize::min((...), i32::MAX as usize) as i32 ? let cutoff = stack.len() as i32 - self.game_size; for (shift, piece) in stack.iter().enumerate() { let shift = shift as i32; // TODO: please don't overflow if shift < cutoff { - self.render_icons(backend, piece.player, row, col, shift); + self.render_icons(details, piece.player, row, col, shift); } else { self.render_stone( - backend, + details, piece.player, piece.stone, row, @@ -195,7 +198,7 @@ impl BoardRenderer { } } - fn render_board(&self, backend: &BoardRendererBackend) { + fn render_board(&self, details: &BoardRendererDetails) { for x in 0..self.game_size { for y in 0..self.game_size { if (x + y) % 2 == 0 { @@ -204,10 +207,10 @@ impl BoardRenderer { set_draw_color(self.odd_square_colour); } draw_rectf( - backend.xorg + x * backend.square_size, - backend.yorg + y * backend.square_size, - backend.square_size, - backend.square_size, + details.xorg + x * details.square_size, + details.yorg + y * details.square_size, + details.square_size, + details.square_size, ); } } @@ -215,25 +218,25 @@ impl BoardRenderer { } struct GUIBoard { - frame: Button, - renderer: BoardRenderer, + button: Button, + renderer: Rc<BoardRenderer>, size: i32, } impl GUIBoard { - fn new(frame: Button, size: i32) -> GUIBoard { - let renderer = BoardRenderer::default().with_size(size); + fn new(button: Button, size: i32) -> GUIBoard { + let renderer = Rc::new(BoardRenderer::default().with_size(size)); let mut g = GUIBoard { - frame, + button, size, renderer, }; - g.frame.draw2(g.render()); + g.button.draw2(g.render()); return g; } - fn render(&self) -> impl Fn(&mut Button) { - let renderer = self.renderer; + fn render(&self) -> impl FnMut(&mut Button) { + let renderer = self.renderer.clone(); let game_size = self.size; let stack = vec![ @@ -279,14 +282,15 @@ impl GUIBoard { }, ]; - move |frame: &mut Button| { - let backend = BoardRendererBackend::initialise(frame, 5, game_size); - renderer.render_board(&backend); + let mut details = BoardRendererDetails::default(); + move |button: &mut Button| { + details.set(button, 5, game_size); + renderer.render_board(&details); // Test code for now - renderer.render_stack(&backend, 1, 4, &stack); - renderer.render_stone(&backend, Player::Black, Stone::Capstone, 1, 2, 0); - renderer.render_stone(&backend, Player::Black, Stone::Standing, 2, 2, 0); + renderer.render_stack(&details, 1, 4, &stack); + renderer.render_stone(&details, Player::Black, Stone::Capstone, 1, 2, 0); + renderer.render_stone(&details, Player::Black, Stone::Standing, 2, 2, 0); } } } @@ -300,7 +304,7 @@ enum GUIMessage { pub struct GUI { app: App, - window: Window, + window: DoubleWindow, board: GUIBoard, log: TextDisplay, sender: Sender<GUIMessage>, @@ -320,7 +324,7 @@ impl GUI { */ // Windows made that way are not resizable? - let mut window = Window::new(0, 0, 800, 600, "Takwrap").center_screen(); + let mut window = DoubleWindow::new(0, 0, 800, 600, "Takwrap").center_screen(); let (sender, receiver) = channel::<GUIMessage>(); @@ -350,17 +354,17 @@ impl GUI { log.set_buffer(Some(TextBuffer::default())); log.insert("test\n"); - let mut board_frame = Button::default() + let mut board_button = Button::default() .with_size(800 - LOG_WIDTH, 600 - menu.height()) .below_of(&menu, 0); - board_frame.set_frame(FrameType::EmbossedBox); - board_frame.emit(sender, GUIMessage::BoardClick); + board_button.set_frame(FrameType::EmbossedBox); + board_button.emit(sender, GUIMessage::BoardClick); - window.resizable(&mut board_frame); + window.resizable(&mut board_button); window.end(); window.show(); - let board = GUIBoard::new(board_frame, 5); + let board = GUIBoard::new(board_button, 5); // button.emit(sender, GUIMessage::Foo); |
