aboutsummaryrefslogtreecommitdiff
path: root/core/src/Model/Template/TableTemplate.cpp
diff options
context:
space:
mode:
authorrtk0c <[email protected]>2022-06-27 18:27:13 -0700
committerrtk0c <[email protected]>2022-06-27 18:27:13 -0700
commit8f0dda5eab181b0f14f2652b4e984aaaae3f258c (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904 /core/src/Model/Template/TableTemplate.cpp
parentfad6a88a13ab1f888ab25ad0aae19c1d63aa0623 (diff)
Start from a clean slate
Diffstat (limited to 'core/src/Model/Template/TableTemplate.cpp')
-rw-r--r--core/src/Model/Template/TableTemplate.cpp591
1 files changed, 0 insertions, 591 deletions
diff --git a/core/src/Model/Template/TableTemplate.cpp b/core/src/Model/Template/TableTemplate.cpp
deleted file mode 100644
index 57caac4..0000000
--- a/core/src/Model/Template/TableTemplate.cpp
+++ /dev/null
@@ -1,591 +0,0 @@
-#include "TableTemplate.hpp"
-
-#include "Utils/IO/StringIntegration.hpp"
-#include "Utils/IO/TslArrayIntegration.hpp"
-#include "Utils/IO/VectorIntegration.hpp"
-
-#include <xlsxwriter.h>
-#include <algorithm>
-#include <charconv>
-#include <cstddef>
-#include <cstdint>
-#include <iostream>
-#include <map>
-
-bool TableCell::IsDataHoldingCell() const
-{
- return IsPrimaryCell() || !IsMergedCell();
-}
-
-bool TableCell::IsPrimaryCell() const
-{
- return PrimaryCellLocation == Location;
-}
-
-bool TableCell::IsMergedCell() const
-{
- return PrimaryCellLocation.x == -1 || PrimaryCellLocation.y == -1;
-}
-
-template <class TTableCell, class TStream>
-void OperateStreamForTableCell(TTableCell& cell, TStream& proxy)
-{
- proxy.template ObjectAdapted<DataStreamAdapters::String>(cell.Content);
- proxy.Object(cell.Location);
- proxy.Object(cell.PrimaryCellLocation);
- proxy.Value(cell.SpanX);
- proxy.Value(cell.SpanY);
- proxy.Enum(cell.HorizontalAlignment);
- proxy.Enum(cell.VerticalAlignment);
- proxy.Enum(cell.Type);
- proxy.Value(cell.DataId);
-}
-
-void TableCell::ReadFromDataStream(InputDataStream& stream)
-{
- ::OperateStreamForTableCell(*this, stream);
-}
-
-void TableCell::WriteToDataStream(OutputDataStream& stream) const
-{
- ::OperateStreamForTableCell(*this, stream);
-}
-
-Vec2i TableArrayGroup::GetLeftCell() const
-{
- return { Row, LeftCell };
-}
-
-Vec2i TableArrayGroup::GetRightCell() const
-{
- return { Row, RightCell };
-}
-
-int TableArrayGroup::GetCount() const
-{
- return RightCell - LeftCell + 1;
-}
-
-Vec2i TableArrayGroup::FindCell(std::string_view name)
-{
- // TODO
- return Vec2i{};
-}
-
-template <class TMap>
-static bool UpdateElementName(TMap& map, std::string_view oldName, std::string_view newName)
-{
- auto iter = map.find(oldName);
- if (iter == map.end()) {
- return false;
- }
-
- auto elm = iter.value();
- auto [DISCARD, inserted] = map.insert(newName, elm);
- if (!inserted) {
- return false;
- }
-
- map.erase(iter);
- return true;
-}
-
-bool TableArrayGroup::UpdateCellName(std::string_view oldName, std::string_view newName)
-{
- return ::UpdateElementName(mName2Cell, oldName, newName);
-}
-
-template <class TTableArrayGroup, class TStream>
-void OperateStreamForTableArrayGroup(TTableArrayGroup& group, TStream& stream)
-{
- stream.Value(group.Row);
- stream.Value(group.LeftCell);
- stream.Value(group.RightCell);
-}
-
-void TableArrayGroup::ReadFromDataStream(InputDataStream& stream)
-{
- ::OperateStreamForTableArrayGroup(*this, stream);
-}
-
-void TableArrayGroup::WriteToDataStream(OutputDataStream& stream) const
-{
- ::OperateStreamForTableArrayGroup(*this, stream);
-}
-
-TableInstantiationParameters::TableInstantiationParameters(const TableTemplate& table)
- : mTable{ &table }
-{
-}
-
-TableInstantiationParameters& TableInstantiationParameters::ResetTable(const TableTemplate& newTable)
-{
- mTable = &newTable;
- return *this;
-}
-
-TableInstantiationParameters TableInstantiationParameters::RebindTable(const TableTemplate& newTable) const
-{
- TableInstantiationParameters result(newTable);
- result.SingularCells = this->SingularCells;
- result.ArrayGroups = this->ArrayGroups;
- return result;
-}
-
-const TableTemplate& TableInstantiationParameters::GetTable() const
-{
- return *mTable;
-}
-
-bool TableTemplate::IsInstance(const Template* tmpl)
-{
- return tmpl->GetKind() == KD_Table;
-}
-
-TableTemplate::TableTemplate()
- : Template(KD_Table)
-{
-}
-
-int TableTemplate::GetTableWidth() const
-{
- return mColumnWidths.size();
-}
-
-int TableTemplate::GetTableHeight() const
-{
- return mRowHeights.size();
-}
-
-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 tableWidth = GetTableWidth();
- int tableHeight = GetTableHeight();
-
- for (int y = 0; y < newHeight; ++y) {
- if (y >= tableHeight) {
- for (int x = 0; x < newWidth; ++x) {
- cells.push_back(TableCell{});
- }
- continue;
- }
-
- for (int x = 0; x < newWidth; ++x) {
- if (x >= tableWidth) {
- cells.push_back(TableCell{});
- } else {
- auto& cell = GetCell({ x, y });
- cells.push_back(std::move(cell));
- }
- }
- }
-
- mCells = std::move(cells);
- mColumnWidths.resize(newWidth, 80);
- mRowHeights.resize(newHeight, 20);
-}
-
-int TableTemplate::GetRowHeight(int row) const
-{
- return mRowHeights[row];
-}
-
-void TableTemplate::SetRowHeight(int row, int height)
-{
- mRowHeights[row] = height;
-}
-
-int TableTemplate::GetColumnWidth(int column) const
-{
- return mColumnWidths[column];
-}
-
-void TableTemplate::SetColumnWidth(int column, int width)
-{
- mColumnWidths[column] = width;
-}
-
-const TableCell& TableTemplate::GetCell(Vec2i pos) const
-{
- int tableWidth = GetTableWidth();
- return mCells[pos.y * tableWidth + pos.x];
-}
-
-TableCell& TableTemplate::GetCell(Vec2i pos)
-{
- return const_cast<TableCell&>(const_cast<const TableTemplate*>(this)->GetCell(pos));
-}
-
-void TableTemplate::SetCellType(Vec2i pos, TableCell::CellType type)
-{
- auto& cell = GetCell(pos);
- if (cell.Type == type) {
- return;
- }
-
- switch (cell.Type) {
- // Nothing to change
- case TableCell::ConstantCell: break;
-
- case TableCell::SingularParametricCell:
- mName2Parameters.erase(cell.Content);
- break;
-
- case TableCell::ArrayParametricCell: {
- auto& ag = mArrayGroups[cell.DataId];
- if (pos.x == ag.LeftCell) {
- ag.LeftCell++;
- } else if (pos.x == ag.RightCell) {
- ag.RightCell--;
- } else {
- }
- } break;
- }
-
- switch (type) {
- // Nothing to do
- case TableCell::ConstantCell: break;
-
- case TableCell::SingularParametricCell: {
- int idx = pos.y * GetTableWidth() + pos.x;
- auto [DISCARD, inserted] = mName2Parameters.insert(cell.Content, idx);
-
- // Duplicate name
- if (!inserted) {
- return;
- }
- } break;
-
- case TableCell::ArrayParametricCell: {
- auto ptr = AddArrayGroup(pos.y, pos.x, pos.x);
-
- // Duplicate name
- if (ptr == nullptr) {
- return;
- }
- } break;
- }
-
- cell.Type = type;
-}
-
-bool TableTemplate::UpdateParameterName(std::string_view oldName, std::string_view newName)
-{
- return ::UpdateElementName(mName2Parameters, oldName, newName);
-}
-
-int TableTemplate::GetArrayGroupCount() const
-{
- return mArrayGroups.size();
-}
-
-const TableArrayGroup& TableTemplate::GetArrayGroup(int id) const
-{
- return mArrayGroups[id];
-}
-
-TableArrayGroup& TableTemplate::GetArrayGroup(int id)
-{
- return mArrayGroups[id];
-}
-
-TableArrayGroup* TableTemplate::AddArrayGroup(int row, int left, int right)
-{
- // size_t max value: 18446744073709551615
- // ^~~~~~~~~~~~~~~~~~~~ 20 chars
- char name[20];
- auto res = std::to_chars(std::begin(name), std::end(name), mArrayGroups.size());
- std::string_view nameStr(name, res.ptr - name);
-
- return AddArrayGroup(nameStr, row, left, right);
-}
-
-TableArrayGroup* TableTemplate::AddArrayGroup(std::string_view name, int row, int left, int right)
-{
- assert(row >= 0 && row < GetTableHeight());
- assert(left >= 0 && left < GetTableWidth());
- assert(right >= 0 && right < GetTableWidth());
-
- // TODO check for overlap
-
- if (left > right) {
- std::swap(left, right);
- }
-
- auto [DISCARD, inserted] = mName2ArrayGroups.insert(name, (int)mArrayGroups.size());
- if (!inserted) {
- return nullptr;
- }
-
- mArrayGroups.push_back(TableArrayGroup{
- .Row = row,
- .LeftCell = left,
- .RightCell = right,
- });
- auto& ag = mArrayGroups.back();
-
- for (int x = left; x <= right; x++) {
- auto& cell = GetCell({ x, row });
-
- // Update type
- cell.Type = TableCell::ArrayParametricCell;
-
- // Insert parameter name lookup
- while (true) {
- auto [DISCARD, inserted] = ag.mName2Cell.insert(cell.Content, x);
- if (inserted) {
- break;
- }
-
- cell.Content += "-";
- }
- }
-
- return &ag;
-}
-
-bool TableTemplate::UpdateArrayGroupName(std::string_view oldName, std::string_view newName)
-{
- return ::UpdateElementName(mName2ArrayGroups, oldName, newName);
-}
-
-bool TableTemplate::ExtendArrayGroupLeft(int id, int n)
-{
- assert(n > 0);
-
- auto& ag = mArrayGroups[id];
- ag.LeftCell -= n;
-
- return false;
-}
-
-bool TableTemplate::ExtendArrayGroupRight(int id, int n)
-{
- assert(n > 0);
-
- auto& ag = mArrayGroups[id];
- ag.RightCell += n;
-
- return false;
-}
-
-TableCell* TableTemplate::FindCell(std::string_view name)
-{
- auto iter = mName2Parameters.find(name);
- if (iter != mName2Parameters.end()) {
- return &mCells[iter.value()];
- } else {
- return nullptr;
- }
-}
-
-TableArrayGroup* TableTemplate::FindArrayGroup(std::string_view name)
-{
- auto iter = mName2ArrayGroups.find(name);
- if (iter != mName2ArrayGroups.end()) {
- return &mArrayGroups[iter.value()];
- } else {
- return nullptr;
- }
-}
-
-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;
-}
-
-lxw_workbook* TableTemplate::InstantiateToExcelWorkbook(const TableInstantiationParameters& params) const
-{
- auto workbook = workbook_new("Table.xlsx");
- InstantiateToExcelWorksheet(workbook, params);
- return workbook;
-}
-
-lxw_worksheet* TableTemplate::InstantiateToExcelWorksheet(lxw_workbook* workbook, const TableInstantiationParameters& params) const
-{
- auto worksheet = workbook_add_worksheet(workbook, "CpltExport.xlsx");
-
- // Map: row number -> length of generated ranges
- std::map<int, int> generatedRanges;
-
- for (size_t i = 0; i < mArrayGroups.size(); ++i) {
- auto& info = mArrayGroups[i];
- auto& param = params.ArrayGroups[i];
-
- auto iter = generatedRanges.find(i);
- if (iter != generatedRanges.end()) {
- int available = iter->second;
- if (available >= param.size()) {
- // Current space is enough to fit in this array group, skip
- continue;
- }
- }
-
- // Not enough space to fit in this array group, update (or insert) the appropriate amount of generated rows
- int row = i;
- int count = param.size();
- generatedRanges.try_emplace(row, count);
- }
-
- auto GetOffset = [&](int y) -> int {
- // std::find_if <values less than y>
- int verticalOffset = 0;
- for (auto it = generatedRanges.begin(); it != generatedRanges.end() && it->first < y; ++it) {
- verticalOffset += it->second;
- }
- return verticalOffset;
- };
-
- auto WriteCell = [&](int row, int col, const TableCell& cell, const char* text) -> void {
- if (cell.IsPrimaryCell()) {
- int lastRow = row + cell.SpanY - 1;
- int lastCol = col + cell.SpanX - 1;
- // When both `string` and `format` are null, the top-left cell contents are untouched (what we just wrote in the above switch)
- worksheet_merge_range(worksheet, row, col, lastRow, lastCol, text, nullptr);
- } else {
- worksheet_write_string(worksheet, row, col, text, nullptr);
- }
- };
-
- // Write/instantiate all array groups
- for (size_t i = 0; i < mArrayGroups.size(); ++i) {
- auto& groupInfo = mArrayGroups[i];
- auto& groupParams = params.ArrayGroups[i];
-
- int rowCellCount = groupInfo.GetCount();
- int rowCount = groupParams.size();
- int baseRowIdx = groupInfo.Row + GetOffset(groupInfo.Row);
-
- // For each row that would be generated
- for (int rowIdx = 0; rowIdx < rowCount; ++rowIdx) {
- auto& row = groupParams[rowIdx];
-
- // For each cell in the row
- for (int rowCellIdx = 0; rowCellIdx < rowCellCount; ++rowCellIdx) {
- // TODO support merged cells in array groups
- worksheet_write_string(worksheet, baseRowIdx + rowIdx, rowCellIdx, row[rowCellIdx].c_str(), nullptr);
- }
- }
- }
-
- int tableWidth = GetTableWidth();
- int tableHeight = GetTableHeight();
-
- // Write all regular and singular parameter cells
- for (int y = 0; y < tableHeight; ++y) {
- for (int x = 0; x < tableWidth; ++x) {
- auto& cell = GetCell({ x, y });
-
- if (!cell.IsDataHoldingCell()) {
- continue;
- }
-
- switch (cell.Type) {
- case TableCell::ConstantCell: {
- int row = y + GetOffset(y);
- int col = x;
-
- WriteCell(row, col, cell, cell.Content.c_str());
- } break;
-
- case TableCell::SingularParametricCell: {
- int row = y + GetOffset(y);
- int col = x;
-
- auto iter = params.SingularCells.find({ x, y });
- if (iter != params.SingularCells.end()) {
- WriteCell(row, col, cell, iter.value().c_str());
- }
- } break;
-
- // See loop above that processes whole array groups at the same time
- case TableCell::ArrayParametricCell: break;
- }
- }
- }
-
- return worksheet;
-}
-
-class TableTemplate::Private
-{
-public:
- template <class TTableTemplate, class TProxy>
- static void OperateStream(TTableTemplate& table, TProxy& proxy)
- {
- proxy.template ObjectAdapted<DataStreamAdapters::Vector<>>(table.mColumnWidths);
- proxy.template ObjectAdapted<DataStreamAdapters::Vector<>>(table.mRowHeights);
- proxy.template ObjectAdapted<DataStreamAdapters::Vector<>>(table.mCells);
- proxy.template ObjectAdapted<DataStreamAdapters::Vector<>>(table.mArrayGroups);
- proxy.template ObjectAdapted<DataStreamAdapters::TslArrayMap<>>(table.mName2Parameters);
- proxy.template ObjectAdapted<DataStreamAdapters::TslArrayMap<>>(table.mName2ArrayGroups);
- }
-};
-
-void TableTemplate::ReadFromDataStream(InputDataStream& stream)
-{
- Private::OperateStream(*this, stream);
-}
-
-void TableTemplate::WriteToDataStream(OutputDataStream& stream) const
-{
- Private::OperateStream(*this, stream);
-}