aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/CMakeLists.txt1
-rw-r--r--core/src/Locale/zh_CN.h8
-rw-r--r--core/src/Model/Template/TableTemplate.cpp25
-rw-r--r--core/src/Model/Template/TableTemplate.hpp19
-rw-r--r--core/src/Model/Template/TableTemplateIterator.cpp52
-rw-r--r--core/src/Model/Template/TableTemplateIterator.hpp35
-rw-r--r--core/src/Model/Template/fwd.hpp2
-rw-r--r--core/src/UI/UI_Items.cpp1
-rw-r--r--core/src/UI/UI_Templates.cpp129
9 files changed, 245 insertions, 27 deletions
diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt
index d3d7496..a14f7d2 100644
--- a/core/CMakeLists.txt
+++ b/core/CMakeLists.txt
@@ -47,6 +47,7 @@ add_source_group(MODEL_TEMPLATE_SOURCES
src/Model/Template/Template_Main.cpp
src/Model/Template/Template_RTTI.cpp
src/Model/Template/TableTemplate.cpp
+ src/Model/Template/TableTemplateIterator.cpp
)
add_source_group(MODEL_WORKFLOW_MODULE_SOURCES
diff --git a/core/src/Locale/zh_CN.h b/core/src/Locale/zh_CN.h
index 02b1e9a..f65744d 100644
--- a/core/src/Locale/zh_CN.h
+++ b/core/src/Locale/zh_CN.h
@@ -124,7 +124,15 @@
#define L10N_TEMPLATE_TABLE "表格模板"
#define L10N_TABLE "表格"
+#define L10N_TABLE_CONFIGURE_PROPERTIES "编辑表格属性..."
+#define L10N_TABLE_PROPERTIES "表格属性"
+#define L10N_TABLE_SINGLE_PARAMS "参数"
+#define L10N_TABLE_ARRAY_GROUPS "列表参数组"
#define L10N_TABLE_CELL "单元格"
+#define L10N_TABLE_CELL_POS "位置:%s%s"
+#define L10N_TABLE_CELL_TYPE_CONST "类型:普通单元格"
+#define L10N_TABLE_CELL_TYPE_PARAM "类型:参数单元格"
+#define L10N_TABLE_CELL_TYPE_CREATE_AG "类型:列表参数组"
#define L10N_TABLE_CELL_CONV "转换类型..."
#define L10N_TABLE_CELL_CONV_CONST "转换为普通单元格"
#define L10N_TABLE_CELL_CONV_PARAM "转换为参数单元格"
diff --git a/core/src/Model/Template/TableTemplate.cpp b/core/src/Model/Template/TableTemplate.cpp
index e01af02..6c3d86b 100644
--- a/core/src/Model/Template/TableTemplate.cpp
+++ b/core/src/Model/Template/TableTemplate.cpp
@@ -20,22 +20,22 @@ bool TableCell::IsMergedCell() const
return PrimaryCellLocation.x == -1 || PrimaryCellLocation.y == -1;
}
-Vec2i TableCellArrayGroup::GetLeftCell() const
+Vec2i TableArrayGroup::GetLeftCell() const
{
return { Row, LeftCell };
}
-Vec2i TableCellArrayGroup::GetRightCell() const
+Vec2i TableArrayGroup::GetRightCell() const
{
return { Row, RightCell };
}
-int TableCellArrayGroup::GetCount() const
+int TableArrayGroup::GetCount() const
{
return RightCell - LeftCell + 1;
}
-Vec2i TableCellArrayGroup::FindCell(std::string_view name)
+Vec2i TableArrayGroup::FindCell(std::string_view name)
{
}
@@ -165,10 +165,11 @@ void TableTemplate::SetCellType(Vec2i pos, TableCell::CellType type)
case TableCell::ArrayParametricCell: {
auto& ag = mArrayGroups[cell.DataId];
if (cell.Location.x == ag.LeftCell) {
-
+ ag.LeftCell++;
} else if (cell.Location.x == ag.RightCell) {
-
+ ag.RightCell--;
} else {
+
}
} break;
}
@@ -205,17 +206,17 @@ int TableTemplate::GetArrayGroupCount() const
return mArrayGroups.size();
}
-const TableCellArrayGroup& TableTemplate::GetArrayGroup(int id) const
+const TableArrayGroup& TableTemplate::GetArrayGroup(int id) const
{
return mArrayGroups[id];
}
-TableCellArrayGroup& TableTemplate::GetArrayGroup(int id)
+TableArrayGroup& TableTemplate::GetArrayGroup(int id)
{
return mArrayGroups[id];
}
-TableCellArrayGroup* TableTemplate::AddArrayGroup(int row, int left, int right)
+TableArrayGroup* TableTemplate::AddArrayGroup(int row, int left, int right)
{
// size_t max value: 18446744073709551615
// ^~~~~~~~~~~~~~~~~~~~ 20 chars
@@ -226,7 +227,7 @@ TableCellArrayGroup* TableTemplate::AddArrayGroup(int row, int left, int right)
return AddArrayGroup(nameStr, row, left, right);
}
-TableCellArrayGroup* TableTemplate::AddArrayGroup(std::string_view name, int row, int left, int right)
+TableArrayGroup* TableTemplate::AddArrayGroup(std::string_view name, int row, int left, int right)
{
assert(row >= 0 && row < GetTableHeight());
assert(left >= 0 && left < GetTableWidth());
@@ -243,7 +244,7 @@ TableCellArrayGroup* TableTemplate::AddArrayGroup(std::string_view name, int row
return nullptr;
}
- mArrayGroups.push_back(TableCellArrayGroup{
+ mArrayGroups.push_back(TableArrayGroup{
.Row = row,
.LeftCell = left,
.RightCell = right,
@@ -281,7 +282,7 @@ TableCell* TableTemplate::FindCell(std::string_view name)
}
}
-TableCellArrayGroup* TableTemplate::FindArrayGroup(std::string_view name)
+TableArrayGroup* TableTemplate::FindArrayGroup(std::string_view name)
{
auto iter = mName2ArrayGroups.find(name);
if (iter != mName2ArrayGroups.end()) {
diff --git a/core/src/Model/Template/TableTemplate.hpp b/core/src/Model/Template/TableTemplate.hpp
index 7f331fa..a9a89d4 100644
--- a/core/src/Model/Template/TableTemplate.hpp
+++ b/core/src/Model/Template/TableTemplate.hpp
@@ -84,7 +84,7 @@ public:
/// \see TableCell
/// \see TableInstantiationParameters
/// \see TableTemplate
-class TableCellArrayGroup
+class TableArrayGroup
{
public:
/// Parameter name mapped to cell location (index from LeftCell).
@@ -108,7 +108,7 @@ public:
struct lxw_workbook;
struct lxw_worksheet;
-/// An object containing the necessary information to instanciate a table template.
+/// An object containing the necessary information to instantiate a table template.
/// \see TableTemplate
class TableInstantiationParameters
{
@@ -137,13 +137,16 @@ public:
/// This current supports exporting to xlsx files.
class TableTemplate : public Template
{
+ friend class TableSingleParamsIter;
+ friend class TableArrayGroupsIter;
+
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<TableCellArrayGroup> mArrayGroups;
+ std::vector<TableArrayGroup> mArrayGroups;
std::vector<int> mRowHeights;
std::vector<int> mColumnWidths;
@@ -165,10 +168,10 @@ public:
void SetCellType(Vec2i pos, TableCell::CellType type);
int GetArrayGroupCount() const;
- const TableCellArrayGroup& GetArrayGroup(int id) const;
- TableCellArrayGroup& GetArrayGroup(int id);
- TableCellArrayGroup* AddArrayGroup(int row, int left, int right);
- TableCellArrayGroup* AddArrayGroup(std::string_view name, int row, int left, int right);
+ 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 ExtendArrayGroupLeft(int id, int n);
bool ExtendArrayGroupRight(int id, int n);
@@ -176,7 +179,7 @@ public:
TableCell* FindCell(std::string_view name);
/// Find an array group by its name.
- TableCellArrayGroup* FindArrayGroup(std::string_view name);
+ TableArrayGroup* FindArrayGroup(std::string_view name);
enum MergeCellsResult
{
diff --git a/core/src/Model/Template/TableTemplateIterator.cpp b/core/src/Model/Template/TableTemplateIterator.cpp
new file mode 100644
index 0000000..19e30b9
--- /dev/null
+++ b/core/src/Model/Template/TableTemplateIterator.cpp
@@ -0,0 +1,52 @@
+#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
new file mode 100644
index 0000000..bf7f517
--- /dev/null
+++ b/core/src/Model/Template/TableTemplateIterator.hpp
@@ -0,0 +1,35 @@
+#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/fwd.hpp b/core/src/Model/Template/fwd.hpp
index b918755..8378871 100644
--- a/core/src/Model/Template/fwd.hpp
+++ b/core/src/Model/Template/fwd.hpp
@@ -2,7 +2,7 @@
// TableTemplate.hpp
class TableCell;
-class TableCellArrayGroup;
+class TableArrayGroup;
class TableInstantiationParameters;
class TableTemplate;
diff --git a/core/src/UI/UI_Items.cpp b/core/src/UI/UI_Items.cpp
index a557eb4..2685c82 100644
--- a/core/src/UI/UI_Items.cpp
+++ b/core/src/UI/UI_Items.cpp
@@ -1,4 +1,5 @@
#include "UI.hpp"
+#include "UI.hpp"
#include "Model/GlobalStates.hpp"
#include "Model/Project.hpp"
diff --git a/core/src/UI/UI_Templates.cpp b/core/src/UI/UI_Templates.cpp
index 5255b6a..b612662 100644
--- a/core/src/UI/UI_Templates.cpp
+++ b/core/src/UI/UI_Templates.cpp
@@ -3,13 +3,16 @@
#include "Model/GlobalStates.hpp"
#include "Model/Project.hpp"
#include "Model/Template/TableTemplate.hpp"
+#include "Model/Template/TableTemplateIterator.hpp"
#include "Model/Template/Template.hpp"
#include "Utils/I18n.hpp"
#include <IconsFontAwesome.h>
#include <imgui.h>
#include <imgui_extra_math.h>
+#include <imgui_internal.h>
#include <imgui_stdlib.h>
+#include <charconv>
#include <fstream>
#include <iostream>
#include <utility>
@@ -138,6 +141,8 @@ public:
private:
void DisplayInspector()
{
+ bool openedDummy = true;
+
// This is an id, no need to localize
if (ImGui::BeginTabBar("Inspector")) {
if (ImGui::BeginTabItem(I18N_TEXT("Cell", L10N_TABLE_CELL))) {
@@ -153,46 +158,124 @@ private:
}
if (ImGui::BeginTabItem(I18N_TEXT("Table", L10N_TABLE))) {
- DisplayTableProperties();
+ // Table properties
+ if (ImGui::Button(I18N_TEXT("Configure table properties...", L10N_TABLE_CONFIGURE_PROPERTIES))) {
+ // Act as if ImGui::OpenPopup is executed in the previous id stack frame (tab bar level)
+ // Note: we can't simply use ImGui::GetItemID() here, because that would return the id of the ImGui::Button
+ auto tabBar = ImGui::GetCurrentContext()->CurrentTabBar;
+ auto id = tabBar->Tabs[tabBar->LastTabItemIdx].ID;
+ ImGui::PopID();
+ ImGui::OpenPopup(I18N_TEXT("Table properties", L10N_TABLE_PROPERTIES));
+ ImGui::PushOverrideID(id);
+ }
+
+ // Table contents
+ DisplayTableContents();
+
ImGui::EndTabItem();
}
+ if (ImGui::BeginPopupModal(I18N_TEXT("Table properties", L10N_TABLE_PROPERTIES), &openedDummy, ImGuiWindowFlags_AlwaysAutoResize)) {
+ DisplayTableProperties();
+ ImGui::EndPopup();
+ }
ImGui::EndTabBar();
}
}
+ static char NthUppercaseLetter(int n)
+ {
+ return (char)((int)'A' + n);
+ }
+
+ static void ExcelRow(int row, char* bufferBegin, char* bufferEnd)
+ {
+ auto res = std::to_chars(bufferBegin, bufferEnd, row);
+ if (res.ec != std::errc()) {
+ return;
+ }
+ }
+
+ static char* ExcelColumn(int column, char* bufferBegin, char* bufferEnd)
+ {
+ // https://stackoverflow.com/a/182924/11323702
+
+ int dividend = column;
+ int modulo;
+
+ char* lastChar = bufferEnd - 1;
+ *lastChar = '\0';
+ char* writeHead = lastChar - 1;
+
+ while (dividend > 0) {
+ if (writeHead < bufferBegin) {
+ return nullptr;
+ }
+
+ modulo = (dividend - 1) % 26;
+
+ *writeHead = NthUppercaseLetter(modulo);
+ --writeHead;
+
+ dividend = (dividend - modulo) / 26;
+ }
+
+ // `writeHead` at this point would be a one-past-the-bufferEnd reverse iterator (i.e. one-past-the-(text)beginning in the bufferBegin)
+ // add 1 to get to the actual beginning of the text
+ return writeHead + 1;
+ }
+
void DisplayCellProperties(Vec2i pos)
{
auto& cell = mTable->GetCell(pos);
auto& uiCell = mUICells[pos.y * mTable->GetTableWidth() + pos.x];
+ char colStr[8]; // 2147483647 -> FXSHRXW, len == 7, along with \0
+ char* colBegin = ExcelColumn(pos.x + 1, std::begin(colStr), std::end(colStr));
+ char rowStr[11]; // len(2147483647) == 10, along with \0
+ ExcelRow(pos.y + 1, std::begin(rowStr), std::end(rowStr));
+ ImGui::Text(I18N_TEXT("Location: %s%s", L10N_TABLE_CELL_POS), colBegin, rowStr);
+
+ switch (cell.Type)
+ {
+ case TableCell::ConstantCell:
+ ImGui::Text(I18N_TEXT("Type: Constant", L10N_TABLE_CELL_TYPE_CONST));
+ break;
+ case TableCell::SingularParametricCell:
+ ImGui::Text(I18N_TEXT("Type: Single parameter", L10N_TABLE_CELL_TYPE_PARAM));
+ break;
+ case TableCell::ArrayParametricCell:
+ ImGui::Text(I18N_TEXT("Type: Array group", L10N_TABLE_CELL_TYPE_CREATE_AG));
+ break;
+ }
+
if (ImGui::Button(I18N_TEXT("Convert to...", L10N_TABLE_CELL_CONV))) {
ImGui::OpenPopup("ConvertCtxMenu");
}
if (ImGui::BeginPopup("ConvertCtxMenu")) {
bool constantDisabled = cell.Type == TableCell::ConstantCell;
- if (ImGui::MenuItem(I18N_TEXT("Convert to regular cell", L10N_TABLE_CELL_CONV_CONST), nullptr, false, constantDisabled)) {
+ if (ImGui::MenuItem(I18N_TEXT("Convert to regular cell", L10N_TABLE_CELL_CONV_CONST), nullptr, false, !constantDisabled)) {
mTable->SetCellType(pos, TableCell::ConstantCell);
}
bool singleDisabled = cell.Type == TableCell::SingularParametricCell;
- if (ImGui::MenuItem(I18N_TEXT("Convert to parameter cell", L10N_TABLE_CELL_CONV_PARAM), nullptr, false, singleDisabled)) {
+ if (ImGui::MenuItem(I18N_TEXT("Convert to parameter cell", L10N_TABLE_CELL_CONV_PARAM), nullptr, false, !singleDisabled)) {
mTable->SetCellType(pos, TableCell::SingularParametricCell);
}
bool arrayDisabled = cell.Type == TableCell::ArrayParametricCell;
- if (ImGui::MenuItem(I18N_TEXT("Add to a new array group", L10N_TABLE_CELL_CONV_CREATE_AG), nullptr, false, arrayDisabled)) {
+ if (ImGui::MenuItem(I18N_TEXT("Add to a new array group", L10N_TABLE_CELL_CONV_CREATE_AG), nullptr, false, !arrayDisabled)) {
mTable->AddArrayGroup(pos.x, pos.x, pos.y);
}
bool leftDisabled = !mSS.HasLeftAG || arrayDisabled;
- if (ImGui::MenuItem(I18N_TEXT("Add to the array group to the left", L10N_TABLE_CELL_CONV_ADD_AG_LEFT), nullptr, false, leftDisabled)) {
+ if (ImGui::MenuItem(I18N_TEXT("Add to the array group to the left", L10N_TABLE_CELL_CONV_ADD_AG_LEFT), nullptr, false, !leftDisabled)) {
auto& leftCell = mTable->GetCell((Vec2i){ pos.x - 1, pos.y });
mTable->ExtendArrayGroupRight(leftCell.DataId, 1);
}
bool rightDisabled = !mSS.HasRightAG || arrayDisabled;
- if (ImGui::MenuItem(I18N_TEXT("Add to the array group to the right", L10N_TABLE_CELL_CONV_ADD_AG_RIGHT), nullptr, false, rightDisabled)) {
+ if (ImGui::MenuItem(I18N_TEXT("Add to the array group to the right", L10N_TABLE_CELL_CONV_ADD_AG_RIGHT), nullptr, false, !rightDisabled)) {
auto& rightCell = mTable->GetCell((Vec2i){ pos.x + 1, pos.y });
mTable->ExtendArrayGroupLeft(rightCell.DataId, 1);
}
@@ -291,6 +374,40 @@ private:
// TODO
}
+ void DisplayTableContents()
+ {
+ if (ImGui::TreeNode(ICON_FA_BONG " " I18N_TEXT("Parameters", L10N_TABLE_SINGLE_PARAMS))) {
+ TableSingleParamsIter iter(*mTable);
+ while (iter.HasNext()) {
+ auto& cell = iter.Next();
+ if (ImGui::Selectable(cell.Content.c_str())) {
+ SelectCell(cell.Location);
+ }
+ }
+ ImGui::TreePop();
+ }
+ if (ImGui::TreeNode(ICON_FA_LIST " " I18N_TEXT("Array groups", L10N_TABLE_ARRAY_GROUPS))) {
+ TableArrayGroupsIter iter(*mTable);
+ // For each array group
+ while (iter.HasNext()) {
+ if (ImGui::TreeNode(iter.PeekNameCStr())) {
+ auto& ag = iter.Peek();
+ // For each cell in the array group
+ for (int x = ag.LeftCell; x <= ag.RightCell; ++x) {
+ Vec2i pos{ x, ag.Row };
+ auto& cell = mTable->GetCell(pos);
+ if (ImGui::Selectable(cell.Content.c_str())) {
+ SelectCell(pos);
+ }
+ }
+ ImGui::TreePop();
+ }
+ iter.Next();
+ }
+ ImGui::TreePop();
+ }
+ }
+
void DisplayTableProperties()
{
// TODO