aboutsummaryrefslogtreecommitdiff
path: root/src/components/MoveTable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/MoveTable.cpp')
-rw-r--r--src/components/MoveTable.cpp280
1 files changed, 280 insertions, 0 deletions
diff --git a/src/components/MoveTable.cpp b/src/components/MoveTable.cpp
new file mode 100644
index 0000000..e7f7af3
--- /dev/null
+++ b/src/components/MoveTable.cpp
@@ -0,0 +1,280 @@
+#include "MoveTable.hpp"
+
+namespace cgeditor {
+
+MoveTable::MoveTable(Status *s) : Component(s) {
+ ImageWidth = status->MoveWidth * 0.25; // Image is 25% of the cell
+}
+void MoveTable::Refresh() {
+ status->MoveTableMaxX = 0;
+ status->MoveTableMaxY = 0;
+ elements.clear();
+ VariationMargins.clear();
+ CurrentMove = -1; // No current move by default
+ if (status->Moves != NULL) {
+ UpdateMoves(status->Moves, 0, 0, status->Moves->IsBlack);
+ // We only set the type after the call to UpdateMoves()
+ // This way only a single move will be the current move
+ if (CurrentMove >= 0) {
+ if (status->UseMoveImages) {
+ elements[CurrentMove].prop |= Property::Current;
+ elements[CurrentMove + 1].prop |= Property::Current;
+ } else {
+ elements[CurrentMove].prop |= Property::Current;
+ }
+ }
+ } else {
+ Element e;
+ e.prop = Property::Text;
+ e.text = "No move to show";
+ e.x = status->MarginBarWidth;
+ e.y = 0;
+ e.height = status->MoveHeight;
+ e.width = -1;
+ elements.push_back(e);
+ }
+}
+
+bool MoveTable::IsMouseOver(const Element &e) const {
+ // Check if we clicked on scroll bars
+ if (status->IsMenuOpen ||
+ status->MouseX >= (status->CanvasWidth - status->ScrollbarWidth) ||
+ status->MouseY >= (status->CanvasHeight - status->ScrollbarWidth)) {
+ return (false);
+ }
+ return (e.IsOver(status->MouseX - status->ScrollX,
+ status->MouseY - status->ScrollY));
+}
+
+std::uint32_t MoveTable::UpdateMoves(CGEHalfMove *m, std::uint32_t line,
+ std::uint32_t indent, bool only_black) {
+
+ //---------- Check black or white ----------
+ char indent_black = 0;
+ if (m->IsBlack) {
+ indent_black++;
+ }
+
+ //---------- Create temporary move surrounding area ----------
+ Element move_bound;
+ move_bound.prop = Property::Move;
+ if (m->IsBlack) {
+ move_bound.prop |= Property::Black;
+ }
+ move_bound.x = status->MarginBarWidth + status->MoveX +
+ status->MoveWidth * (indent + indent_black) +
+ ((indent + 1) / 2 * status->MarginBarWidth);
+ move_bound.y = status->MoveHeight * line;
+ move_bound.width = status->MoveWidth;
+ move_bound.height = status->MoveHeight;
+ move_bound.text = m->move;
+ move_bound.ShouldApplyScroll = true;
+ bool isMouseOver = IsMouseOver(move_bound);
+
+ //---------- Update current focus move ----------
+ if (isMouseOver) {
+ if (status->LeftClick) {
+ if (!status->IsMenuOpen) {
+ status->Events.push_back({Event::Type::Goto, m});
+ status->CurrentMove = m;
+ }
+ } else if (status->RightClick) {
+ status->IsMenuOpen = true;
+ status->SelectedMove = m;
+ }
+ }
+
+ //---------- Check if current move is focused ----------
+ if (status->CurrentMove == m) {
+ CurrentMove = elements.size();
+ }
+
+ //---------- Draw move ----------
+ if (status->UseMoveImages) {
+ // Image
+ Element img;
+ img.prop = Property::Image | Property::Move;
+ img.x = move_bound.x;
+ img.y = status->MoveHeight * line;
+ img.width = ImageWidth;
+ img.height = status->MoveHeight;
+ img.ShouldApplyScroll = true;
+ elements.push_back(img);
+ // Move
+ Element e;
+ e.prop = move_bound.prop | Property::Text;
+ e.text = m->move;
+ e.x = ImageWidth + move_bound.x;
+ e.y = status->MoveHeight * line;
+ e.width = status->MoveWidth - ImageWidth;
+ e.height = status->MoveHeight;
+ e.ShouldApplyScroll = true;
+ elements.push_back(e);
+ } else {
+ move_bound.prop |= Property::Text;
+ elements.push_back(move_bound);
+ }
+
+ //---------- Move number in marge or for variation ----------
+ if (indent == 0 && (!m->IsBlack || only_black)) {
+ DRAW_NB(0, status->MoveHeight * line, m->Number);
+ } else if (indent > 0 && (!m->IsBlack || only_black)) {
+ if (only_black) {
+ DRAW_NB_VAR((move_bound.x - status->MoveWidth) - status->MarginBarWidth,
+ status->MoveHeight * line, m->Number);
+ } else {
+ DRAW_NB_VAR(move_bound.x - ((indent + 1) / 2 * status->MarginBarWidth),
+ status->MoveHeight * line, m->Number);
+ }
+ }
+
+ //---------- Draw dots ----------
+ if (only_black) {
+ DRAW_DOTS(move_bound.x - status->MoveWidth, move_bound.y);
+ }
+
+ //---------- Scrolling infos ----------
+ if ((move_bound.x + move_bound.width) > status->MoveTableMaxX) {
+ status->MoveTableMaxX = move_bound.x + move_bound.width;
+ }
+ if ((move_bound.y + move_bound.height) > status->MoveTableMaxY) {
+ status->MoveTableMaxY = move_bound.y + move_bound.height;
+ }
+
+ //---------- Comments ----------
+ if (m->GetNbLineComment() > 0) {
+ line = DrawComment(m, line, indent, move_bound, indent_black);
+ }
+
+ //---------- Variations ----------
+ if (m->variations.size() > 0) {
+ line = DrawVariations(m, line, indent, move_bound, indent_black);
+ }
+
+ //---------- Mainline ----------
+ if (m->MainLine != NULL) {
+ only_black = (m->MainLine->IsBlack &&
+ (m->GetNbLineComment() > 0 || m->variations.size()));
+ if (m->IsBlack) {
+ line = UpdateMoves(m->MainLine, line + 1, indent, only_black);
+ } else {
+ line = UpdateMoves(m->MainLine, line, indent, only_black);
+ }
+ }
+
+ return (line);
+}
+
+std::uint32_t MoveTable::DrawComment(CGEHalfMove *m, std::uint32_t line,
+ std::uint32_t indent,
+ const Element &move_bound,
+ const char &indent_black) {
+ // Show three dots
+ if (!m->IsBlack) {
+ DRAW_DOTS(status->MarginBarWidth + status->MoveX +
+ status->MoveWidth * (indent + 1) +
+ ((indent + 1) / 2 * status->MarginBarWidth),
+ status->MoveHeight * line);
+ }
+ // Print comment
+ line++;
+ // Computer number of rows for the comment
+ std::uint16_t CommentRows = m->GetNbLineComment() / status->CommentLinePerRow;
+ if (m->GetNbLineComment() % status->CommentLinePerRow > 0) {
+ CommentRows++;
+ }
+ // Draw comment
+ Element e;
+ e.prop = Property::Text | Property::Comment;
+ e.x = move_bound.x -
+ (indent_black *
+ status->MoveWidth); // status->MarginBarWidth + status->MoveX;
+ e.y = status->MoveHeight * line;
+ e.width = -1; // Negative width means expands to the edge of the canvas
+ e.height = CommentRows * status->MoveHeight;
+ e.text = m->GetComment();
+ e.ShouldApplyScroll = true;
+ elements.push_back(e);
+ // Do not forget to add marging before comment
+ if (indent > 0) {
+ e.x -= status->MarginBarWidth;
+ VariationMargins.push_back(e);
+ }
+ if (status->LeftClick && IsMouseOver(e)) {
+ status->Events.push_back({Event::Type::CommentSelected, m});
+ }
+ line += CommentRows; // Skip right amount of lines
+ // Since we already increment line for black later on:
+ if (m->IsBlack || m->variations.size() > 0) {
+ line--;
+ }
+
+ return (line);
+}
+
+std::uint32_t MoveTable::DrawVariations(CGEHalfMove *m, std::uint32_t line,
+ std::uint32_t indent,
+ const Element &move_bound,
+ const char &indent_black) {
+ // Show three dots next to move if white turn
+ if ((m->variations.size() == 0) && !m->IsBlack) {
+ DRAW_DOTS(status->MarginBarWidth + status->MoveX +
+ status->MoveWidth * (indent + 1),
+ status->MoveHeight * line);
+ }
+ // Show button on the right side of the move
+ {
+ Element e;
+ e.prop = Property::Rectangle | Property::Button;
+ e.x = move_bound.x + status->MoveWidth;
+ if (!m->IsBlack)
+ e.x += status->MoveWidth;
+ e.y = move_bound.y + std::ceil(status->MoveHeight / 4);
+ e.width = std::ceil(status->MoveHeight / 2);
+ e.height = e.width;
+ e.ShouldApplyScroll = true;
+ if (status->LeftClick && IsMouseOver(e)) {
+ m->Folded = !m->Folded;
+ }
+ if (!m->Folded) {
+ e.prop |= Property::On;
+ }
+ elements.push_back(e);
+ }
+ if (!m->Folded) {
+ for (CGEHalfMove *v : m->variations) {
+ // For each variation show show/hide button
+ {
+ Element e;
+ e.prop = Property::Rectangle | Property::Button;
+ e.x = (status->MarginBarWidth + status->MoveX +
+ status->MoveWidth * indent) +
+ status->MoveWidth - std::ceil(status->MoveHeight / 2) -
+ std::ceil(status->MoveHeight / 4);
+ e.y = (status->MoveHeight * (line + 1)) +
+ std::ceil(status->MoveHeight / 4);
+ e.width = std::ceil(status->MoveHeight / 2);
+ e.height = e.width;
+ e.ShouldApplyScroll = true;
+ if (status->LeftClick && IsMouseOver(e)) {
+ v->Hide = !v->Hide;
+ }
+ if (!v->Hide) {
+ e.prop |= Property::On;
+ }
+ elements.push_back(e);
+ }
+ if (!v->Hide) {
+ line = UpdateMoves(v, line + 1, indent + 1, v->IsBlack);
+ } else {
+ line++;
+ }
+ }
+ }
+ // New line after variation
+ if (m->MainLine != NULL && m->MainLine->IsBlack) {
+ line++;
+ }
+ return (line);
+}
+} // namespace cgeditor \ No newline at end of file