diff options
Diffstat (limited to 'core/src/Model/Template/TableTemplate.cpp')
-rw-r--r-- | core/src/Model/Template/TableTemplate.cpp | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/core/src/Model/Template/TableTemplate.cpp b/core/src/Model/Template/TableTemplate.cpp new file mode 100644 index 0000000..caf0e21 --- /dev/null +++ b/core/src/Model/Template/TableTemplate.cpp @@ -0,0 +1,119 @@ +#include "TableTemplate.hpp" + +bool TableCell::IsPrimaryCell() const +{ + return PrimaryCellLocation == Location; +} + +bool TableCell::IsMergedCell() const +{ + return PrimaryCellLocation.x == -1 || PrimaryCellLocation.y == -1; +} + +int TableTemplate::GetTableWidth() const +{ + return mTableWidth; +} + +int TableTemplate::GetTableHeight() const +{ + return mTableHeight; +} + +void TableTemplate::Resize(int newWidth, int newHeight) +{ + // TODO this doesn't gracefully handle resizing to a smaller size which trims some merged cells + + std::vector<TableCell> cells; + cells.reserve(newWidth * newHeight); + + int yEnd = std::min(mTableHeight, newHeight); + int xEnd = std::min(mTableWidth, newWidth); + for (int y = 0; y < yEnd; ++y) { + if (y >= mTableHeight) { + for (int x = 0; x < xEnd; ++x) { + cells.push_back(TableCell{}); + } + continue; + } + + for (int x = 0; x < xEnd; ++x) { + if (x >= mTableWidth) { + cells.push_back(TableCell{}); + } else { + auto& cell = GetCell({ x, y }); + cells.push_back(std::move(cell)); + } + } + } + + mCells = std::move(cells); +} + +const TableCell& TableTemplate::GetCell(Vec2i pos) const +{ + return mCells[pos.y * mTableWidth + pos.x]; +} + +TableCell& TableTemplate::GetCell(Vec2i pos) +{ + return const_cast<TableCell&>(const_cast<const TableTemplate*>(this)->GetCell(pos)); +} + +TableTemplate::MergeCellsResult TableTemplate::MergeCells(Vec2i topLeft, Vec2i bottomRight) +{ + auto SortTwo = [](int& a, int& b) { + if (a > b) { + std::swap(a, b); + } + }; + SortTwo(topLeft.x, bottomRight.x); + SortTwo(topLeft.y, bottomRight.y); + + auto ResetProgress = [&]() { + for (int y = topLeft.y; y < bottomRight.y; ++y) { + for (int x = topLeft.x; x < bottomRight.x; ++x) { + auto& cell = GetCell({ x, y }); + cell.PrimaryCellLocation = { -1, -1 }; + } + } + }; + + for (int y = topLeft.y; y < bottomRight.y; ++y) { + for (int x = topLeft.x; x < bottomRight.x; ++x) { + auto& cell = GetCell({ x, y }); + if (cell.IsMergedCell()) { + ResetProgress(); + return MCR_CellAlreadyMerged; + } + + cell.PrimaryCellLocation = topLeft; + } + } + + auto& primaryCell = GetCell(topLeft); + primaryCell.SpanX = bottomRight.x - topLeft.x; + primaryCell.SpanY = bottomRight.y - topLeft.y; + + return MCR_Success; +} + +TableTemplate::BreakCellsResult TableTemplate::BreakCells(Vec2i topLeft) +{ + auto& primaryCell = GetCell(topLeft); + if (!primaryCell.IsMergedCell()) { + return BCR_CellNotMerged; + } + + for (int dy = 0; dy < primaryCell.SpanY; ++dy) { + for (int dx = 0; dx < primaryCell.SpanX; ++dx) { + auto& cell = GetCell({ topLeft.x + dx, topLeft.y + dy }); + cell.PrimaryCellLocation = { -1, -1 }; + } + } + + primaryCell.SpanX = 1; + primaryCell.SpanY = 1; + + return BCR_Success; +} |