diff options
Diffstat (limited to 'core/src')
-rw-r--r-- | core/src/Locale/zh_CN.h | 8 | ||||
-rw-r--r-- | core/src/Model/Template/TableTemplate.cpp | 25 | ||||
-rw-r--r-- | core/src/Model/Template/TableTemplate.hpp | 19 | ||||
-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/fwd.hpp | 2 | ||||
-rw-r--r-- | core/src/UI/UI_Items.cpp | 1 | ||||
-rw-r--r-- | core/src/UI/UI_Templates.cpp | 129 |
8 files changed, 244 insertions, 27 deletions
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 |