aboutsummaryrefslogtreecommitdiff
path: root/app/source/Cplt/Model/Template/TableTemplate.hpp
diff options
context:
space:
mode:
authorrtk0c <[email protected]>2022-06-30 21:38:53 -0700
committerrtk0c <[email protected]>2022-06-30 21:38:53 -0700
commit7fe47a9d5b1727a61dc724523b530762f6d6ba19 (patch)
treee95be6e66db504ed06d00b72c579565bab873277 /app/source/Cplt/Model/Template/TableTemplate.hpp
parent2cf952088d375ac8b2f45b144462af0953436cff (diff)
Restructure project
Diffstat (limited to 'app/source/Cplt/Model/Template/TableTemplate.hpp')
-rw-r--r--app/source/Cplt/Model/Template/TableTemplate.hpp223
1 files changed, 223 insertions, 0 deletions
diff --git a/app/source/Cplt/Model/Template/TableTemplate.hpp b/app/source/Cplt/Model/Template/TableTemplate.hpp
new file mode 100644
index 0000000..3e931d4
--- /dev/null
+++ b/app/source/Cplt/Model/Template/TableTemplate.hpp
@@ -0,0 +1,223 @@
+#pragma once
+
+#include <Cplt/Model/Template/Template.hpp>
+#include <Cplt/Utils/Vector.hpp>
+#include <Cplt/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;
+};