summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
Diffstat (limited to 'core/src')
-rw-r--r--core/src/Locale/zh_CN.h4
-rw-r--r--core/src/Model/Template/TableTemplate.cpp42
-rw-r--r--core/src/Model/Template/TableTemplate.hpp12
-rw-r--r--core/src/UI/UI_Templates.cpp194
4 files changed, 202 insertions, 50 deletions
diff --git a/core/src/Locale/zh_CN.h b/core/src/Locale/zh_CN.h
index f65744d..632c229 100644
--- a/core/src/Locale/zh_CN.h
+++ b/core/src/Locale/zh_CN.h
@@ -126,6 +126,10 @@
#define L10N_TABLE "表格"
#define L10N_TABLE_CONFIGURE_PROPERTIES "编辑表格属性..."
#define L10N_TABLE_PROPERTIES "表格属性"
+#define L10N_TABLE_DO_RESIZE "调整表格大小..."
+#define L10N_TABLE_RESIZE "调整表格大小"
+#define L10N_TABLE_WIDTH "宽度"
+#define L10N_TABLE_HEIGHT "长度"
#define L10N_TABLE_SINGLE_PARAMS "参数"
#define L10N_TABLE_ARRAY_GROUPS "列表参数组"
#define L10N_TABLE_CELL "单元格"
diff --git a/core/src/Model/Template/TableTemplate.cpp b/core/src/Model/Template/TableTemplate.cpp
index 6c3d86b..ce1d6a5 100644
--- a/core/src/Model/Template/TableTemplate.cpp
+++ b/core/src/Model/Template/TableTemplate.cpp
@@ -39,6 +39,29 @@ Vec2i TableArrayGroup::FindCell(std::string_view name)
{
}
+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);
+}
+
TableInstantiationParameters::TableInstantiationParameters(const TableTemplate& table)
: mTable{ &table }
{
@@ -164,12 +187,11 @@ void TableTemplate::SetCellType(Vec2i pos, TableCell::CellType type)
case TableCell::ArrayParametricCell: {
auto& ag = mArrayGroups[cell.DataId];
- if (cell.Location.x == ag.LeftCell) {
+ if (pos.x == ag.LeftCell) {
ag.LeftCell++;
- } else if (cell.Location.x == ag.RightCell) {
+ } else if (pos.x == ag.RightCell) {
ag.RightCell--;
} else {
-
}
} break;
}
@@ -180,7 +202,7 @@ void TableTemplate::SetCellType(Vec2i pos, TableCell::CellType type)
case TableCell::SingularParametricCell: {
int idx = pos.y * GetTableWidth() + pos.x;
- auto [DISCARD, inserted] = mName2Parameters.emplace(cell.Content, idx);
+ auto [DISCARD, inserted] = mName2Parameters.insert(cell.Content, idx);
// Duplicate name
if (!inserted) {
@@ -201,6 +223,11 @@ void TableTemplate::SetCellType(Vec2i pos, TableCell::CellType type)
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();
@@ -239,7 +266,7 @@ TableArrayGroup* TableTemplate::AddArrayGroup(std::string_view name, int row, in
std::swap(left, right);
}
- auto [DISCARD, inserted] = mName2ArrayGroups.emplace(name, (int)mArrayGroups.size());
+ auto [DISCARD, inserted] = mName2ArrayGroups.insert(name, (int)mArrayGroups.size());
if (!inserted) {
return nullptr;
}
@@ -252,6 +279,11 @@ TableArrayGroup* TableTemplate::AddArrayGroup(std::string_view name, int row, in
return &mArrayGroups.back();
}
+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);
diff --git a/core/src/Model/Template/TableTemplate.hpp b/core/src/Model/Template/TableTemplate.hpp
index a9a89d4..141e952 100644
--- a/core/src/Model/Template/TableTemplate.hpp
+++ b/core/src/Model/Template/TableTemplate.hpp
@@ -32,6 +32,7 @@ public:
};
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.
@@ -102,6 +103,7 @@ public:
/// 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);
};
// Forward declaration of libxlsxwriter structs
@@ -165,13 +167,23 @@ public:
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);
diff --git a/core/src/UI/UI_Templates.cpp b/core/src/UI/UI_Templates.cpp
index b612662..b4e3aa5 100644
--- a/core/src/UI/UI_Templates.cpp
+++ b/core/src/UI/UI_Templates.cpp
@@ -16,6 +16,7 @@
#include <fstream>
#include <iostream>
#include <utility>
+#include <variant>
namespace {
class TemplateUI
@@ -59,14 +60,18 @@ private:
/* Selection states */
union
{
+ // Initialize to this element
+ std::monostate mIdleState{};
+
/// "CS" stands for "Constant cell selection States"
struct
{
- } mCS{}; // Initialize to this element
+ } mCS;
/// "SS" stands for "Singular parameter selection States".
struct
{
+ std::string EditBuffer;
bool ErrorDuplicateVarName;
bool HasLeftAG;
bool HasRightAG;
@@ -75,10 +80,20 @@ private:
/// "AS" stands for "Array group parameter selection States".
struct
{
+ std::string EditBuffer;
bool ErrorDuplicateVarName;
} mAS;
+
+ // "RS" stands for "Range selection States".
+ struct
+ {
+ } mRS;
};
+ /* Table resizer dialog states */
+ int mNewTableWidth;
+ int mNewTableHeight;
+
/* Table states */
bool mDirty = false;
bool mFirstDraw = true;
@@ -93,6 +108,36 @@ public:
Resize(6, 5);
}
+ virtual ~TableTemplateUI() override
+ {
+ // We can't move this to be a destructor of the union
+ // because that way it would run after the destruction of mTable
+ if (!IsSelected()) {
+ // Case: mIdleState
+ // Noop
+ } else if (mSelectionTL == mSelectionBR) {
+ switch (mTable->GetCell(mSelectionTL).Type) {
+ case TableCell::ConstantCell:
+ // Case: mCS
+ // Noop
+ break;
+
+ case TableCell::SingularParametricCell:
+ // Case: mSS
+ mSS.EditBuffer.std::string::~string();
+ break;
+
+ case TableCell::ArrayParametricCell:
+ // Case: mAS
+ mAS.EditBuffer.std::string::~string();
+ break;
+ }
+ } else {
+ // Case: mRS
+ // Noop
+ }
+ }
+
virtual void Display() override
{
ImGui::Columns(2);
@@ -157,16 +202,24 @@ private:
ImGui::EndTabItem();
}
+ auto OpenPopup = [](const char* name) {
+ // 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(name);
+ ImGui::PushOverrideID(id);
+ };
if (ImGui::BeginTabItem(I18N_TEXT("Table", L10N_TABLE))) {
- // 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);
+ OpenPopup(I18N_TEXT("Table properties", L10N_TABLE_PROPERTIES));
+ }
+
+ if (ImGui::Button(I18N_TEXT("Resize table...", L10N_TABLE_DO_RESIZE))) {
+ mNewTableWidth = mTable->GetTableWidth();
+ mNewTableHeight = mTable->GetTableHeight();
+ OpenPopup(I18N_TEXT("Resize table", L10N_TABLE_RESIZE));
}
// Table contents
@@ -178,6 +231,10 @@ private:
DisplayTableProperties();
ImGui::EndPopup();
}
+ if (ImGui::BeginPopupModal(I18N_TEXT("Resize table", L10N_TABLE_RESIZE), &openedDummy, ImGuiWindowFlags_AlwaysAutoResize)) {
+ DisplayTableResizer();
+ ImGui::EndPopup();
+ }
ImGui::EndTabBar();
}
@@ -236,8 +293,7 @@ private:
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)
- {
+ switch (cell.Type) {
case TableCell::ConstantCell:
ImGui::Text(I18N_TEXT("Type: Constant", L10N_TABLE_CELL_TYPE_CONST));
break;
@@ -253,31 +309,36 @@ private:
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)) {
+ bool constantEnabled = cell.Type != TableCell::ConstantCell;
+ if (ImGui::MenuItem(I18N_TEXT("Convert to regular cell", L10N_TABLE_CELL_CONV_CONST), nullptr, false, constantEnabled)) {
mTable->SetCellType(pos, TableCell::ConstantCell);
+ ResetCS();
}
- bool singleDisabled = cell.Type == TableCell::SingularParametricCell;
- if (ImGui::MenuItem(I18N_TEXT("Convert to parameter cell", L10N_TABLE_CELL_CONV_PARAM), nullptr, false, !singleDisabled)) {
+ bool singleEnabled = cell.Type != TableCell::SingularParametricCell;
+ if (ImGui::MenuItem(I18N_TEXT("Convert to parameter cell", L10N_TABLE_CELL_CONV_PARAM), nullptr, false, singleEnabled)) {
mTable->SetCellType(pos, TableCell::SingularParametricCell);
+ ResetSS(pos);
}
- 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)) {
- mTable->AddArrayGroup(pos.x, pos.x, pos.y);
+ bool arrayEnabled = cell.Type != TableCell::ArrayParametricCell;
+ if (ImGui::MenuItem(I18N_TEXT("Add to a new array group", L10N_TABLE_CELL_CONV_CREATE_AG), nullptr, false, arrayEnabled)) {
+ mTable->AddArrayGroup(pos.x, pos.x, pos.y); // Use automatically generated name
+ ResetAS(pos);
}
- 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)) {
- auto& leftCell = mTable->GetCell((Vec2i){ pos.x - 1, pos.y });
+ bool leftEnabled = mSS.HasLeftAG && arrayEnabled;
+ if (ImGui::MenuItem(I18N_TEXT("Add to the array group to the left", L10N_TABLE_CELL_CONV_ADD_AG_LEFT), nullptr, false, leftEnabled)) {
+ auto& leftCell = mTable->GetCell({ pos.x - 1, pos.y });
mTable->ExtendArrayGroupRight(leftCell.DataId, 1);
+ ResetAS(pos);
}
- 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)) {
- auto& rightCell = mTable->GetCell((Vec2i){ pos.x + 1, pos.y });
+ bool rightEnabled = mSS.HasRightAG && arrayEnabled;
+ if (ImGui::MenuItem(I18N_TEXT("Add to the array group to the right", L10N_TABLE_CELL_CONV_ADD_AG_RIGHT), nullptr, false, rightEnabled)) {
+ auto& rightCell = mTable->GetCell({ pos.x + 1, pos.y });
mTable->ExtendArrayGroupLeft(rightCell.DataId, 1);
+ ResetAS(pos);
}
ImGui::EndPopup();
@@ -339,9 +400,16 @@ private:
break;
case TableCell::SingularParametricCell:
- if (ImGui::InputText(I18N_TEXT("Variable name", L10N_TABLE_CELL_VAR_NAME), &cell.Content)) {
- auto c = mTable->FindCell(cell.Content);
- mSS.ErrorDuplicateVarName = c != nullptr;
+ if (ImGui::InputText(I18N_TEXT("Variable name", L10N_TABLE_CELL_VAR_NAME), &mSS.EditBuffer)) {
+ // Sync name change to table
+ bool success = mTable->UpdateParameterName(cell.Content, mSS.EditBuffer);
+ if (success) {
+ // Flush name to display content
+ cell.Content = mSS.EditBuffer;
+ mSS.ErrorDuplicateVarName = false;
+ } else {
+ mSS.ErrorDuplicateVarName = true;
+ }
}
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip(I18N_TEXT("Name of the parameter link to this cell.", L10N_TABLE_CELL_VAR_TOOLTIP));
@@ -353,10 +421,15 @@ private:
break;
case TableCell::ArrayParametricCell:
- if (ImGui::InputText(I18N_TEXT("Variable name", L10N_TABLE_CELL_VAR_NAME), &cell.Content)) {
+ if (ImGui::InputText(I18N_TEXT("Variable name", L10N_TABLE_CELL_VAR_NAME), &mAS.EditBuffer)) {
auto ag = mTable->GetArrayGroup(cell.DataId);
- auto cl = ag.FindCell(cell.Content);
- mAS.ErrorDuplicateVarName = cl.x != -1 && cl.y != -1;
+ bool success = ag.UpdateCellName(cell.Content, mAS.EditBuffer);
+ if (success) {
+ cell.Content = mAS.EditBuffer;
+ mAS.ErrorDuplicateVarName = false;
+ } else {
+ mAS.ErrorDuplicateVarName = true;
+ }
}
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip(I18N_TEXT("Name of the parameter lnk to this cell; local within the array group.", L10N_TABLE_CELL_ARRAY_VAR_TOOLTIP));
@@ -413,6 +486,21 @@ private:
// TODO
}
+ void DisplayTableResizer()
+ {
+ ImGui::InputInt(I18N_TEXT("Width", L10N_TABLE_WIDTH), &mNewTableWidth);
+ ImGui::InputInt(I18N_TEXT("Height", L10N_TABLE_HEIGHT), &mNewTableHeight);
+
+ if (ImGui::Button(I18N_TEXT("Confirm", L10N_CONFIRM))) {
+ ImGui::CloseCurrentPopup();
+ Resize(mNewTableWidth, mNewTableHeight);
+ }
+ ImGui::SameLine();
+ if (ImGui::Button(I18N_TEXT("Cancel", L10N_CANCEL))) {
+ ImGui::CloseCurrentPopup();
+ }
+ }
+
void DisplayTable()
{
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8, 8));
@@ -561,12 +649,12 @@ private:
mSelectionTL = { -1, -1 };
mSelectionBR = { -1, -1 };
- ResetCS();
+ ResetIdleState();
}
- void ResetCS()
+ void ResetIdleState()
{
- mCS = {};
+ mIdleState = {};
}
void SelectRange(Vec2i p1, Vec2i p2)
@@ -588,33 +676,49 @@ private:
uiCell.Selected = true;
});
- ResetAS();
+ ResetRS();
}
- void ResetSS(Vec2i pos)
+ void ResetRS()
{
- mSS = {};
- mSS.ErrorDuplicateVarName = false;
- mSS.HasLeftAG = pos.x > 1 && mTable->GetCell({ pos.x - 1, pos.y }).Type == TableCell::ArrayParametricCell;
- mSS.HasRightAG = pos.x < mTable->GetTableWidth() - 1 && mTable->GetCell({ pos.x + 1, pos.y }).Type == TableCell::ArrayParametricCell;
+ mRS = {};
}
- void SelectCell(Vec2i cell)
+ void SelectCell(Vec2i pos)
{
ClearSelection();
- mSelectionTL = cell;
- mSelectionBR = cell;
+ mSelectionTL = pos;
+ mSelectionBR = pos;
- int i = cell.y * mTable->GetTableWidth() + cell.x;
+ int i = pos.y * mTable->GetTableWidth() + pos.x;
mUICells[i].Selected = true;
- ResetSS(cell);
+ switch (mTable->GetCell(pos).Type) {
+ case TableCell::ConstantCell: ResetCS(); break;
+ case TableCell::SingularParametricCell: ResetSS(pos); break;
+ case TableCell::ArrayParametricCell: ResetAS(pos); break;
+ }
+ }
+
+ void ResetCS()
+ {
+ mCS = {};
+ }
+
+ void ResetSS(Vec2i pos)
+ {
+ mSS = {};
+ mSS.EditBuffer = mTable->GetCell(pos).Content;
+ mSS.ErrorDuplicateVarName = false;
+ mSS.HasLeftAG = pos.x > 1 && mTable->GetCell({ pos.x - 1, pos.y }).Type == TableCell::ArrayParametricCell;
+ mSS.HasRightAG = pos.x < mTable->GetTableWidth() - 1 && mTable->GetCell({ pos.x + 1, pos.y }).Type == TableCell::ArrayParametricCell;
}
- void ResetAS()
+ void ResetAS(Vec2i pos)
{
mAS = {};
+ mAS.EditBuffer = mTable->GetCell(pos).Content;
mAS.ErrorDuplicateVarName = false;
}
};