diff options
Diffstat (limited to 'src/game_tab/left_panel/board/BoardCanvas.cpp')
| -rw-r--r-- | src/game_tab/left_panel/board/BoardCanvas.cpp | 294 |
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() |
