aboutsummaryrefslogtreecommitdiff
path: root/src/game_tab/left_panel/board/BoardCanvas.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/game_tab/left_panel/board/BoardCanvas.cpp')
-rw-r--r--src/game_tab/left_panel/board/BoardCanvas.cpp294
1 files changed, 294 insertions, 0 deletions
diff --git a/src/game_tab/left_panel/board/BoardCanvas.cpp b/src/game_tab/left_panel/board/BoardCanvas.cpp
new file mode 100644
index 0000000..237a68a
--- /dev/null
+++ b/src/game_tab/left_panel/board/BoardCanvas.cpp
@@ -0,0 +1,294 @@
+#include "BoardCanvas.hpp"
+
+wxDEFINE_EVENT(PLAY_MOVE_EVENT, wxCommandEvent);
+
+BoardCanvas::BoardCanvas(wxFrame *parent)
+ : wxPanel(parent), black_side(false), is_black_turn(true), frozen(false),
+ lock_square_size(false), t(new Theme()), t_captures(new Theme()) {
+ board = "rnbqkbnrpppppppp PPPPPPPPRNBQKBNR";
+ is_dragging = false;
+ valid_drag = false;
+ t_captures->ResizePieces(t->GetPiecesSizes() * CAPTURE_FACTOR);
+ SetClockTime(-1, -1, -1, false);
+ SetClockTime(-1, -1, -1, true);
+ ApplyPreferences();
+}
+
+BoardCanvas::BoardCanvas(wxFrame *parent, std::uint32_t square_width,
+ bool frozen)
+ : BoardCanvas(parent) {
+ t->ResizeSquaresAndPieces(square_width);
+ t_captures->ResizePieces(t->GetPiecesSizes() * CAPTURE_FACTOR);
+ this->frozen = true;
+ lock_square_size = true;
+}
+
+void BoardCanvas::OnPaint(wxPaintEvent &event) {
+ wxPaintDC dc(this);
+ REFRESH_MOUSE_LOCATION();
+ square_width = t->GetSquaresSizes();
+ canvas_size = dc.GetSize();
+ boardX = (canvas_size.x - (8 * square_width)) / 2;
+ boardY = (canvas_size.y - (8 * square_width)) / 2;
+ if (boardX > canvas_size.x)
+ boardX = 0;
+ if (boardY > canvas_size.y)
+ boardY = 0;
+ DrawBoard(dc);
+}
+
+void BoardCanvas::ApplyPreferences() {
+ if (t != NULL)
+ delete t;
+ if (t_captures != NULL)
+ delete t_captures;
+ t = new Theme();
+ t_captures = new Theme();
+
+ CONFIG_OPEN(config);
+ black_side = config->Read("board/black_by_default", false);
+ if (lock_square_size) {
+ t->ResizeSquaresAndPieces(square_width);
+ } else {
+ t->ResizeSquaresAndPieces(config->Read("board/square_size", 80));
+ }
+ t->SetSquareRadius(config->Read("board/corner_radius", 10));
+ t_captures->ResizePieces(t->GetPiecesSizes() * CAPTURE_FACTOR);
+ CONFIG_CLOSE(config);
+
+ Refresh();
+}
+
+void BoardCanvas::SetupBoard(std::string board, bool is_black_turn,
+ std::map<char, std::uint8_t> captures) {
+ this->board = board;
+ this->is_black_turn = is_black_turn;
+ this->captures = captures;
+ Refresh();
+}
+
+void BoardCanvas::DrawBoard(wxPaintDC &dc) {
+ std::uint32_t piece_width = t->GetPiecesSizes();
+ std::uint32_t centrer_offset = (square_width - piece_width) / 2;
+
+ bool DrawDraggingPiece = false;
+ char dp = 'p';
+ std::uint32_t dpx = 0, dpy = 0;
+ for (std::int8_t file = 7; file >= 0; file--) {
+ for (std::uint8_t rank = 0; rank <= 7; rank++) {
+ std::uint32_t x = boardX + (7 - file) * square_width;
+ std::uint32_t y = boardY + rank * square_width;
+ if ((file + rank) % 2 == 0) {
+ if (file == 0 && rank == 0) {
+ dc.DrawBitmap(*t->Get('1'), x, y, true);
+ } else if (file == 7 && rank == 7) {
+ dc.DrawBitmap(*t->Get('2'), x, y, true);
+ } else {
+ dc.DrawBitmap(*t->Get('s'), x, y, true);
+ }
+ } else {
+ if (file == 7 && rank == 0) {
+ dc.DrawBitmap(*t->Get('0'), x, y, true);
+ } else if (file == 0 && rank == 7) {
+ dc.DrawBitmap(*t->Get('3'), x, y, true);
+ } else {
+ dc.DrawBitmap(*t->Get('S'), x, y, true);
+ }
+ }
+
+ std::uint8_t prank = rank;
+ std::uint8_t pfile = file;
+ if (black_side) {
+ prank = 7 - rank;
+ pfile = 7 - file;
+ }
+ std::uint32_t px = x + centrer_offset;
+ std::uint32_t py = y + centrer_offset;
+ char piece = board[(7 - pfile) + 8 * prank];
+ if (is_dragging && (7 - pfile) == active_square.x &&
+ (7 - prank) == active_square.y) {
+ dp = piece;
+ dpx = px - (lastClickX - mouseX);
+ dpy = py - (lastClickY - mouseY);
+ DrawDraggingPiece = true;
+ continue;
+ }
+ if (piece != ' ') {
+ dc.DrawBitmap(*t->Get(piece), px, py, false);
+ }
+ }
+ }
+
+ // Draw badge
+ dc.SetPen(wxPen(*wxBLACK, 3));
+ std::uint32_t badgeY = boardY;
+ std::uint32_t badgeWidth = square_width / 2;
+ if (is_black_turn) {
+ dc.SetBrush(*wxBLACK_BRUSH);
+ if (black_side) {
+ badgeY = boardY + (8 * square_width) - badgeWidth;
+ }
+ } else {
+ dc.SetBrush(*wxWHITE_BRUSH);
+ if (!black_side) {
+ badgeY = boardY + (8 * square_width) - badgeWidth;
+ }
+ }
+ wxRect badge(boardX + (8 * square_width) + badgeWidth / 2, badgeY, badgeWidth,
+ badgeWidth);
+ dc.DrawRectangle(badge);
+
+ // Draw captures first for white then for black
+ std::uint32_t captures_size = t_captures->GetPiecesSizes();
+ std::uint8_t padding = 10;
+ std::uint32_t offsetX = 0;
+ std::uint32_t offsetY = -(captures_size + padding);
+ if (black_side) {
+ offsetY = 8 * square_width + padding;
+ }
+ for (char p : {'P', 'N', 'B', 'R', 'Q'}) {
+ if (captures.find(p) != captures.end()) {
+ for (std::uint8_t i = 0; i < captures[p]; i++) {
+ dc.DrawBitmap(*t_captures->Get(p), boardX + offsetX, boardY + offsetY);
+ offsetX += captures_size / 2;
+ }
+ offsetX += captures_size / 2;
+ }
+ }
+ offsetX = 0;
+ if (black_side) {
+ offsetY = -(captures_size + padding);
+ } else {
+ offsetY = 8 * square_width + padding;
+ }
+ for (char p : {'p', 'n', 'b', 'r', 'q'}) {
+ if (captures.find(p) != captures.end()) {
+ for (std::uint8_t i = 0; i < captures[p]; i++) {
+ dc.DrawBitmap(*t_captures->Get(p), boardX + offsetX, boardY + offsetY);
+ offsetX += captures_size / 2;
+ }
+ offsetX += captures_size / 2;
+ }
+ }
+
+ // Draw dragging piece
+ if (DrawDraggingPiece) {
+ dc.DrawBitmap(*t->Get(dp), dpx, dpy, false);
+ }
+
+ // Draw numbers
+ for (char l = 'a'; l < 'a' + 8; l++) {
+ dc.DrawText(wxString(l), wxPoint(boardX + l - 'a' * square_width,
+ boardY + 8 * square_width + 10));
+ }
+
+ // Draw Clocks
+ if (std::get<0>(black_time) >= 0) {
+ wxFont font = dc.GetFont();
+ ClockTime clock = black_side ? white_time : black_time;
+ wxString time =
+ wxString::Format("%ds", std::get<1>(clock), std::get<2>(clock));
+ if (std::get<0>(clock) > 0) {
+ time = wxString::Format("%d:%d", std::get<0>(clock), std::get<1>(clock));
+ } else if (std::get<1>(clock) > 0) {
+ time = wxString::Format("%d:%ds", std::get<1>(clock), std::get<2>(clock));
+ }
+ dc.SetFont(font.Scale(1.5).MakeBold());
+ wxCoord width, height;
+ dc.GetTextExtent(time, &width, &height);
+ dc.DrawText(time,
+ wxPoint(boardX + square_width * 8 - width, boardY - height));
+ clock = black_side ? black_time : white_time;
+ time = wxString::Format("%ds", std::get<1>(clock), std::get<2>(clock));
+ if (std::get<0>(clock) > 0) {
+ time = wxString::Format("%d:%d", std::get<0>(clock), std::get<1>(clock));
+ } else if (std::get<1>(clock) > 0) {
+ time = wxString::Format("%d:%ds", std::get<1>(clock), std::get<2>(clock));
+ }
+ dc.GetTextExtent(time, &width, &height);
+ dc.DrawText(time, wxPoint(boardX + square_width * 8 - width,
+ boardY + square_width * 8));
+ }
+}
+
+void BoardCanvas::MouseEvent(wxMouseEvent &event) {
+ if (!frozen) {
+ if (event.Dragging()) {
+ if (valid_drag) {
+ is_dragging = true;
+ Refresh();
+ }
+ } else {
+ if (is_dragging) {
+ is_dragging = false;
+ valid_drag = false;
+ // Handle drop
+ REFRESH_MOUSE_LOCATION();
+ INIT_CURRENT_SQUARE();
+
+ if (IsCurrentSquareValid) {
+ wxLogDebug("Drag end on square (%d,%d)", file, rank);
+ /// Play the move
+ wxCommandEvent event(PLAY_MOVE_EVENT, GetId());
+ event.SetEventObject(this);
+ std::string move = ((char)('a' + active_square.x)) +
+ std::to_string(+active_square.y + 1) +
+ ((char)('a' + file)) + std::to_string(rank + 1);
+ event.SetString(move);
+ ProcessEvent(event);
+ }
+ }
+ if (event.LeftDown()) {
+ SetFocus();
+ REFRESH_MOUSE_LOCATION();
+ lastClickX = mouseX;
+ lastClickY = mouseY;
+ INIT_CURRENT_SQUARE();
+ if (IsCurrentSquareValid) {
+ active_square.x = file;
+ active_square.y = rank;
+ if (board[(7 - rank) * 8 + file] != ' ') {
+ wxLogDebug("Drag start on square (%d,%d)", file, rank);
+ valid_drag = true;
+ }
+ }
+ }
+ }
+ }
+}
+
+void BoardCanvas::Zoom(std::int32_t zoom) {
+ t->Zoom(zoom);
+ t_captures->ResizePieces(t->GetPiecesSizes() * CAPTURE_FACTOR);
+ Refresh();
+}
+
+void BoardCanvas::Swap() {
+ black_side = !black_side;
+ Refresh();
+}
+
+void BoardCanvas::OnKeyEvent(wxKeyEvent &event) {
+ if (event.GetKeyCode() == WXK_LEFT) {
+ wxCommandEvent previousEvent(PREVIOUS_MOVE_EVENT, GetId());
+ previousEvent.SetEventObject(this);
+ ProcessEvent(previousEvent);
+ } else if (event.GetKeyCode() == WXK_RIGHT) {
+ wxCommandEvent nextEvent(NEXT_MOVE_EVENT, GetId());
+ nextEvent.SetEventObject(this);
+ ProcessEvent(nextEvent);
+ }
+}
+
+void BoardCanvas::SetClockTime(short hours, short min, short sec,
+ bool IsBlack) {
+ if (IsBlack) {
+ black_time = std::make_tuple(hours, min, sec);
+ } else {
+ white_time = std::make_tuple(hours, min, sec);
+ }
+}
+
+wxBEGIN_EVENT_TABLE(BoardCanvas, wxPanel) EVT_PAINT(BoardCanvas::OnPaint)
+ EVT_MOUSE_EVENTS(BoardCanvas::MouseEvent)
+ EVT_CHAR_HOOK(BoardCanvas::OnKeyEvent) wxEND_EVENT_TABLE()