aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gui.rs108
1 files changed, 56 insertions, 52 deletions
diff --git a/src/gui.rs b/src/gui.rs
index e84d6ce..f7c7cac 100644
--- a/src/gui.rs
+++ b/src/gui.rs
@@ -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);