diff options
author | rtk0c <[email protected]> | 2022-06-30 21:38:53 -0700 |
---|---|---|
committer | rtk0c <[email protected]> | 2022-06-30 21:38:53 -0700 |
commit | 7fe47a9d5b1727a61dc724523b530762f6d6ba19 (patch) | |
tree | e95be6e66db504ed06d00b72c579565bab873277 /core/src/Model/Template | |
parent | 2cf952088d375ac8b2f45b144462af0953436cff (diff) |
Restructure project
Diffstat (limited to 'core/src/Model/Template')
-rw-r--r-- | core/src/Model/Template/TableTemplate.cpp | 591 | ||||
-rw-r--r-- | core/src/Model/Template/TableTemplate.hpp | 223 | ||||
-rw-r--r-- | core/src/Model/Template/TableTemplateIterator.cpp | 52 | ||||
-rw-r--r-- | core/src/Model/Template/TableTemplateIterator.hpp | 35 | ||||
-rw-r--r-- | core/src/Model/Template/Template.hpp | 68 | ||||
-rw-r--r-- | core/src/Model/Template/Template_Main.cpp | 214 | ||||
-rw-r--r-- | core/src/Model/Template/Template_RTTI.cpp | 29 | ||||
-rw-r--r-- | core/src/Model/Template/fwd.hpp | 11 |
8 files changed, 0 insertions, 1223 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); -} diff --git a/core/src/Model/Template/TableTemplate.hpp b/core/src/Model/Template/TableTemplate.hpp deleted file mode 100644 index 8771867..0000000 --- a/core/src/Model/Template/TableTemplate.hpp +++ /dev/null @@ -1,223 +0,0 @@ -#pragma once - -#include "Model/Template/Template.hpp" -#include "Utils/Vector.hpp" -#include "Utils/VectorHash.hpp" -#include "cplt_fwd.hpp" - -#include <tsl/array_map.h> -#include <tsl/robin_map.h> -#include <string> -#include <string_view> -#include <vector> - -class TableCell -{ -public: - enum TextAlignment - { - /// For horizontal alignment, this means align left. For vertical alignment, this means align top. - AlignAxisMin, - /// Align middle of the text to the middle of the axis. - AlignCenter, - /// For horizontal alignment, this means align right. For vertical alignment, this means align bottom. - AlignAxisMax, - }; - - enum CellType - { - ConstantCell, - SingularParametricCell, - ArrayParametricCell, - }; - -public: - /// Display content of this cell. This doesn't necessarily have to line up with the parameter name (if this cell is one). - std::string Content; - Vec2i Location; - /// Location of the primary (top left) cell, if this cell is a part of a merged group. - /// Otherwise, either component of this field shall be -1. - Vec2i PrimaryCellLocation{ -1, -1 }; - int SpanX = 0; - int SpanY = 0; - TextAlignment HorizontalAlignment = AlignCenter; - TextAlignment VerticalAlignment = AlignCenter; - CellType Type = ConstantCell; - /// The id of the group description object, if this cell isn't a constant or singular parameter cell. Otherwise, this value is -1. - int DataId = -1; - -public: - /// Return whether this cell holds meaningful data, i.e. true when this cell is either unmerged or the primary cell of a merged range. - bool IsDataHoldingCell() const; - /// Return whether this cell is the primary (i.e. top left) cell of a merged range or not. - bool IsPrimaryCell() const; - /// Return whether this cell is a part of a merged range or not. Includes the primary cell. - bool IsMergedCell() const; - - void ReadFromDataStream(InputDataStream& stream); - void WriteToDataStream(OutputDataStream& stream) const; -}; - -// TODO support reverse (bottom to top) filling order -// TODO support horizontal filling order - -/// Parameter group information for a grouped array of cells. When instantiated, an array of 0 or more -/// elements shall be provided by the user, which will replace the group of templated cells with a list -/// of rows, each instantiated with the n-th element in the provided array. -/// \code -/// [["foo", "bar", "foobar"], -/// ["a", "b", c"], -/// ["1", "2", "3"], -/// ["x", "y", "z"]] -/// // ... may be more -/// \endcode -/// This would create 4 rows of data in the place of the original parameter group. -/// -/// If more than one array parameter groups are on the same row, they would share space between each other: -/// \code -/// | 2 elements was fed to it -/// | | 1 element was fed to it -/// V V -/// {~~~~~~~~~~~~~~~~}{~~~~~~~~~~~~~~} -/// +------+---------+---------------+ -/// | Foo | Example | Another group | -/// +------+---------+---------------+ -/// | Cool | Example | | -/// +------+---------+---------------+ -/// \endcode -/// -/// \see TableCell -/// \see TableInstantiationParameters -/// \see TableTemplate -class TableArrayGroup -{ -public: - /// Parameter name mapped to cell location (index from LeftCell). - tsl::array_map<char, int> mName2Cell; - int Row; - /// Leftmost cell in this group - int LeftCell; - /// Rightmost cell in this group - int RightCell; - -public: - Vec2i GetLeftCell() const; - Vec2i GetRightCell() const; - int GetCount() const; - - /// Find the location of the cell within this array group that has the given name. - Vec2i FindCell(std::string_view name); - bool UpdateCellName(std::string_view oldName, std::string_view newName); - - void ReadFromDataStream(InputDataStream& stream); - void WriteToDataStream(OutputDataStream& stream) const; -}; - -// Forward declaration of libxlsxwriter structs -struct lxw_workbook; -struct lxw_worksheet; - -/// An object containing the necessary information to instantiate a table template. -/// \see TableTemplate -class TableInstantiationParameters -{ -private: - const TableTemplate* mTable; - -public: - tsl::robin_map<Vec2i, std::string> SingularCells; - - using ArrayGroupRow = std::vector<std::string>; - using ArrayGroupData = std::vector<ArrayGroupRow>; - std::vector<ArrayGroupData> ArrayGroups; - -public: - TableInstantiationParameters(const TableTemplate& table); - - TableInstantiationParameters& ResetTable(const TableTemplate& newTable); - TableInstantiationParameters RebindTable(const TableTemplate& newTable) const; - - const TableTemplate& GetTable() const; -}; - -/// A table template, where individual cells can be filled by workflows instantiating this template. Merged cells, -/// parametric rows/columns, and grids are also supported. -/// -/// This current supports exporting to xlsx files. -class TableTemplate : public Template -{ - friend class TableSingleParamsIter; - friend class TableArrayGroupsIter; - class Private; - -private: - /// Map from parameter name to index of the parameter cell (stored in mCells). - tsl::array_map<char, int> mName2Parameters; - /// Map from array group name to the index of the array group (stored in mArrayGroups). - tsl::array_map<char, int> mName2ArrayGroups; - std::vector<TableCell> mCells; - std::vector<TableArrayGroup> mArrayGroups; - std::vector<int> mRowHeights; - std::vector<int> mColumnWidths; - -public: - static bool IsInstance(const Template* tmpl); - TableTemplate(); - - int GetTableWidth() const; - int GetTableHeight() const; - void Resize(int newWidth, int newHeight); - - int GetRowHeight(int row) const; - void SetRowHeight(int row, int height); - int GetColumnWidth(int column) const; - void SetColumnWidth(int column, int width); - - const TableCell& GetCell(Vec2i pos) const; - TableCell& GetCell(Vec2i pos); - /// <ul> - /// <li> In case of becoming a SingularParametricCell: the parameter name is filled with TableCell::Content. - /// <li> In case of becoming a ArrayGroupParametricCell: the array group name is automatically generated as the nth group it would be come. - /// i.e., if there aRe currently 3 groups, the newly created group would be named "4". - /// If this name collides with an existing group, hyphens \c - will be append to the name until no collision happens. - /// </ul> - void SetCellType(Vec2i pos, TableCell::CellType type); - - /// Updates the parameter cell to a new name. Returns true on success and false on failure (param not found or name duplicates). - bool UpdateParameterName(std::string_view oldName, std::string_view newName); - - int GetArrayGroupCount() const; - const TableArrayGroup& GetArrayGroup(int id) const; - TableArrayGroup& GetArrayGroup(int id); - TableArrayGroup* AddArrayGroup(int row, int left, int right); - TableArrayGroup* AddArrayGroup(std::string_view name, int row, int left, int right); - bool UpdateArrayGroupName(std::string_view oldName, std::string_view newName); - bool ExtendArrayGroupLeft(int id, int n); - bool ExtendArrayGroupRight(int id, int n); - - /// Find a singular parameter cell by its name. This does not include cells within an array group. - TableCell* FindCell(std::string_view name); - - /// Find an array group by its name. - TableArrayGroup* FindArrayGroup(std::string_view name); - - enum MergeCellsResult - { - MCR_CellAlreadyMerged, - MCR_Success, - }; - MergeCellsResult MergeCells(Vec2i topLeft, Vec2i bottomRight); - - enum BreakCellsResult - { - BCR_CellNotMerged, - BCR_Success, - }; - BreakCellsResult BreakCells(Vec2i topLeft); - - lxw_workbook* InstantiateToExcelWorkbook(const TableInstantiationParameters& params) const; - lxw_worksheet* InstantiateToExcelWorksheet(lxw_workbook* workbook, const TableInstantiationParameters& params) const; - - void ReadFromDataStream(InputDataStream& stream) override; - void WriteToDataStream(OutputDataStream& stream) const override; -}; diff --git a/core/src/Model/Template/TableTemplateIterator.cpp b/core/src/Model/Template/TableTemplateIterator.cpp deleted file mode 100644 index 19e30b9..0000000 --- a/core/src/Model/Template/TableTemplateIterator.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "TableTemplateIterator.hpp" - -TableSingleParamsIter::TableSingleParamsIter(TableTemplate& tmpl) - : mTemplate{ &tmpl } - , mIter{ tmpl.mName2Parameters.begin() } -{ -} - -bool TableSingleParamsIter::HasNext() const -{ - return mIter != mTemplate->mName2Parameters.end(); -} - -TableCell& TableSingleParamsIter::Next() -{ - int id = mIter.value(); - ++mIter; - - return mTemplate->mCells[id]; -} - -TableArrayGroupsIter::TableArrayGroupsIter(TableTemplate& tmpl) - : mTemplate{ &tmpl } - , mIter{ tmpl.mName2ArrayGroups.begin() } -{ -} - -bool TableArrayGroupsIter::HasNext() const -{ - return mIter != mTemplate->mName2ArrayGroups.end(); -} - -TableArrayGroup& TableArrayGroupsIter::Peek() const -{ - int id = mIter.value(); - return mTemplate->mArrayGroups[id]; -} - -std::string_view TableArrayGroupsIter::PeekName() const -{ - return mIter.key_sv(); -} - -const char* TableArrayGroupsIter::PeekNameCStr() const -{ - return mIter.key(); -} - -void TableArrayGroupsIter::Next() -{ - ++mIter; -} diff --git a/core/src/Model/Template/TableTemplateIterator.hpp b/core/src/Model/Template/TableTemplateIterator.hpp deleted file mode 100644 index bf7f517..0000000 --- a/core/src/Model/Template/TableTemplateIterator.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include "Model/Template/TableTemplate.hpp" -#include "Model/Template/Template.hpp" - -#include <string_view> - -class TableSingleParamsIter -{ -private: - TableTemplate* mTemplate; - tsl::array_map<char, int>::iterator mIter; - -public: - TableSingleParamsIter(TableTemplate& tmpl); - - bool HasNext() const; - TableCell& Next(); -}; - -class TableArrayGroupsIter -{ -private: - TableTemplate* mTemplate; - tsl::array_map<char, int>::iterator mIter; - -public: - TableArrayGroupsIter(TableTemplate& tmpl); - - bool HasNext() const; - TableArrayGroup& Peek() const; - std::string_view PeekName() const; - const char* PeekNameCStr() const; - void Next(); -}; diff --git a/core/src/Model/Template/Template.hpp b/core/src/Model/Template/Template.hpp deleted file mode 100644 index 061cc07..0000000 --- a/core/src/Model/Template/Template.hpp +++ /dev/null @@ -1,68 +0,0 @@ -#pragma once - -#include "Model/Assets.hpp" -#include "cplt_fwd.hpp" - -#include <filesystem> -#include <iosfwd> -#include <memory> -#include <string> - -class Template : public Asset -{ -public: - enum Kind - { - KD_Table, - - InvalidKind, - KindCount = InvalidKind, - }; - - using CategoryType = TemplateAssetList; - -private: - Kind mKind; - -public: - static const char* FormatKind(Kind kind); - static std::unique_ptr<Template> CreateByKind(Kind kind); - - static bool IsInstance(const Template* tmpl); - - Template(Kind kind); - ~Template() override = default; - - Kind GetKind() const; - - virtual void ReadFromDataStream(InputDataStream& stream) = 0; - virtual void WriteToDataStream(OutputDataStream& stream) const = 0; -}; - -class TemplateAssetList final : public AssetListTyped<Template> -{ -private: - // AC = Asset Creator - std::string mACNewName; - NameSelectionError mACNewNameError = NameSelectionError::Empty; - Template::Kind mACNewKind = Template::InvalidKind; - -public: - // Inherit constructors - using AssetListTyped::AssetListTyped; - -protected: - void DiscoverFiles(const std::function<void(SavedAsset)>& callback) const override; - - std::string RetrieveNameFromFile(const std::filesystem::path& file) const override; - uuids::uuid RetrieveUuidFromFile(const std::filesystem::path& file) const override; - std::filesystem::path RetrievePathFromAsset(const SavedAsset& asset) const override; - - bool SaveInstance(const SavedAsset& assetInfo, const Asset* asset) const override; - Template* LoadInstance(const SavedAsset& assetInfo) const override; - Template* CreateInstance(const SavedAsset& assetInfo) const override; - bool RenameInstanceOnDisk(const SavedAsset& assetInfo, std::string_view oldName) const override; - - void DisplayAssetCreator(ListState& state) override; - void DisplayDetailsTable(ListState& state) const override; -}; diff --git a/core/src/Model/Template/Template_Main.cpp b/core/src/Model/Template/Template_Main.cpp deleted file mode 100644 index 4d6b67c..0000000 --- a/core/src/Model/Template/Template_Main.cpp +++ /dev/null @@ -1,214 +0,0 @@ -#include "Template.hpp" - -#include "Model/GlobalStates.hpp" -#include "Model/Project.hpp" -#include "UI/UI.hpp" -#include "Utils/I18n.hpp" -#include "Utils/IO/Archive.hpp" -#include "Utils/UUID.hpp" - -#include <imgui.h> -#include <imgui_stdlib.h> -#include <algorithm> -#include <cstdint> -#include <fstream> - -using namespace std::literals::string_view_literals; -namespace fs = std::filesystem; - -Template::Template(Kind kind) - : mKind{ kind } -{ -} - -Template::Kind Template::GetKind() const -{ - return mKind; -} - -void TemplateAssetList::DiscoverFiles(const std::function<void(SavedAsset)>& callback) const -{ - auto dir = GetConnectedProject().GetTemplatesDirectory(); - DiscoverFilesByExtension(callback, dir, ".cplt-template"sv); -} - -std::string TemplateAssetList::RetrieveNameFromFile(const fs::path& file) const -{ - auto res = DataArchive::LoadFile(file); - if (!res) return ""; - auto& stream = res.value(); - - SavedAsset assetInfo; - stream.ReadObject(assetInfo); - - return assetInfo.Name; -} - -uuids::uuid TemplateAssetList::RetrieveUuidFromFile(const fs::path& file) const -{ - return uuids::uuid::from_string(file.stem().string()); -} - -fs::path TemplateAssetList::RetrievePathFromAsset(const SavedAsset& asset) const -{ - auto fileName = uuids::to_string(asset.Uuid); - return GetConnectedProject().GetTemplatePath(fileName); -} - -bool TemplateAssetList::SaveInstance(const SavedAsset& assetInfo, const Asset* asset) const -{ - auto path = RetrievePathFromAsset(assetInfo); - auto res = DataArchive::SaveFile(path); - if (!res) return false; - auto& stream = res.value(); - - stream.WriteObject(assetInfo); - // This cast is fine: calls to this class will always be wrapped in TypedAssetList<T>, which will ensure `asset` points to some Template - if (auto tmpl = static_cast<const Template*>(asset)) { // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) - stream.WriteObject(*tmpl); - } - - return true; -} - -static std::unique_ptr<Template> LoadTemplateFromFile(const fs::path& path) -{ - auto res = DataArchive::LoadFile(path); - if (!res) return nullptr; - auto& stream = res.value(); - - SavedAsset assetInfo; - stream.ReadObject(assetInfo); - - auto kind = static_cast<Template::Kind>(assetInfo.Payload); - auto tmpl = Template::CreateByKind(kind); - stream.ReadObject(*tmpl); - - return tmpl; -} - -Template* TemplateAssetList::LoadInstance(const SavedAsset& assetInfo) const -{ - return ::LoadTemplateFromFile(RetrievePathFromAsset(assetInfo)).release(); -} - -Template* TemplateAssetList::CreateInstance(const SavedAsset& assetInfo) const -{ - auto kind = static_cast<Template::Kind>(assetInfo.Payload); - return Template::CreateByKind(kind).release(); -} - -bool TemplateAssetList::RenameInstanceOnDisk(const SavedAsset& assetInfo, std::string_view oldName) const -{ - // Get asset path, which is only dependent on UUID - auto path = RetrievePathFromAsset(assetInfo); - - auto tmpl = ::LoadTemplateFromFile(path); - if (!tmpl) return false; - - // Rewrite the asset with the updated name (note the given assetInfo already has the update name) - SaveInstance(assetInfo, tmpl.get()); - - return true; -} - -void TemplateAssetList::DisplayAssetCreator(ListState& state) -{ - auto ValidateNewName = [&]() -> void { - if (mACNewName.empty()) { - mACNewNameError = NameSelectionError::Empty; - return; - } - - if (FindByName(mACNewName)) { - mACNewNameError = NameSelectionError::Duplicated; - return; - } - - mACNewNameError = NameSelectionError::None; - }; - - auto ShowNewNameErrors = [&]() -> void { - switch (mACNewNameError) { - case NameSelectionError::None: break; - case NameSelectionError::Duplicated: - ImGui::ErrorMessage(I18N_TEXT("Duplicate name", L10N_DUPLICATE_NAME_ERROR)); - break; - case NameSelectionError::Empty: - ImGui::ErrorMessage(I18N_TEXT("Name cannot be empty", L10N_EMPTY_NAME_ERROR)); - break; - } - }; - - auto ShowNewKindErrors = [&]() -> void { - if (mACNewKind == Template::InvalidKind) { - ImGui::ErrorMessage(I18N_TEXT("Invalid template type", L10N_TEMPLATE_INVALID_TYPE_ERROR)); - } - }; - - auto IsInputValid = [&]() -> bool { - return mACNewNameError == NameSelectionError::None && - mACNewKind != Template::InvalidKind; - }; - - auto ResetState = [&]() -> void { - mACNewName.clear(); - mACNewKind = Template::InvalidKind; - ValidateNewName(); - }; - - if (ImGui::InputText(I18N_TEXT("Name", L10N_NAME), &mACNewName)) { - ValidateNewName(); - } - - if (ImGui::BeginCombo(I18N_TEXT("Type", L10N_TYPE), Template::FormatKind(mACNewKind))) { - for (int i = 0; i < Template::KindCount; ++i) { - auto kind = static_cast<Template::Kind>(i); - if (ImGui::Selectable(Template::FormatKind(kind), mACNewKind == kind)) { - mACNewKind = kind; - } - } - ImGui::EndCombo(); - } - - ShowNewNameErrors(); - ShowNewKindErrors(); - - if (ImGui::Button(I18N_TEXT("OK", L10N_CONFIRM), !IsInputValid())) { - ImGui::CloseCurrentPopup(); - - Create(SavedAsset{ - .Name = mACNewName, - .Payload = static_cast<uint64_t>(mACNewKind), - }); - ResetState(); - } - ImGui::SameLine(); - if (ImGui::Button(I18N_TEXT("Cancel", L10N_CANCEL))) { - ImGui::CloseCurrentPopup(); - } -} - -void TemplateAssetList::DisplayDetailsTable(ListState& state) const -{ - ImGui::BeginTable("AssetDetailsTable", 2, ImGuiTableFlags_Borders); - - ImGui::TableSetupColumn(I18N_TEXT("Name", L10N_NAME)); - ImGui::TableSetupColumn(I18N_TEXT("Type", L10N_TYPE)); - ImGui::TableHeadersRow(); - - for (auto& asset : this->GetAssets()) { - ImGui::TableNextRow(); - - ImGui::TableNextColumn(); - if (ImGui::Selectable(asset.Name.c_str(), state.SelectedAsset == &asset, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_DontClosePopups)) { - state.SelectedAsset = &asset; - } - - ImGui::TableNextColumn(); - auto kind = static_cast<Template::Kind>(asset.Payload); - ImGui::TextUnformatted(Template::FormatKind(kind)); - } - - ImGui::EndTable(); -} diff --git a/core/src/Model/Template/Template_RTTI.cpp b/core/src/Model/Template/Template_RTTI.cpp deleted file mode 100644 index d1affe7..0000000 --- a/core/src/Model/Template/Template_RTTI.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "Template.hpp" - -#include "Model/Template/TableTemplate.hpp" -#include "Utils/I18n.hpp" - -const char* Template::FormatKind(Kind kind) -{ - switch (kind) { - case KD_Table: return I18N_TEXT("Table template", L10N_TEMPLATE_TABLE); - - case InvalidKind: break; - } - return ""; -} - -std::unique_ptr<Template> Template::CreateByKind(Kind kind) -{ - switch (kind) { - case KD_Table: return std::make_unique<TableTemplate>(); - - case InvalidKind: break; - } - return nullptr; -} - -bool Template::IsInstance(const Template* tmpl) -{ - return true; -} diff --git a/core/src/Model/Template/fwd.hpp b/core/src/Model/Template/fwd.hpp deleted file mode 100644 index 8378871..0000000 --- a/core/src/Model/Template/fwd.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -// TableTemplate.hpp -class TableCell; -class TableArrayGroup; -class TableInstantiationParameters; -class TableTemplate; - -// Template.hpp -class Template; -class TemplateAssetList; |