diff options
Diffstat (limited to 'core/src/UI')
-rw-r--r-- | core/src/UI/UI.hpp | 2 | ||||
-rw-r--r-- | core/src/UI/UI_Templates.cpp | 166 | ||||
-rw-r--r-- | core/src/UI/UI_Utils.cpp | 9 |
3 files changed, 168 insertions, 9 deletions
diff --git a/core/src/UI/UI.hpp b/core/src/UI/UI.hpp index 0a80b4c..b0f0a6f 100644 --- a/core/src/UI/UI.hpp +++ b/core/src/UI/UI.hpp @@ -13,6 +13,8 @@ void PopDisabled(); bool Button(const char* label, bool disabled); bool Button(const char* label, const ImVec2& sizeArg, bool disabled); +bool MenuItemConditional(const char* name, bool disabled); + void ErrorIcon(); void ErrorMessage(const char* fmt, ...); void WarningIcon(); diff --git a/core/src/UI/UI_Templates.cpp b/core/src/UI/UI_Templates.cpp index ab9c317..e77bef3 100644 --- a/core/src/UI/UI_Templates.cpp +++ b/core/src/UI/UI_Templates.cpp @@ -25,6 +25,10 @@ public: virtual void Display() = 0; }; +// Table template styles +constexpr ImU32 kSingleParamOutline = IM_COL32(255, 255, 0, 255); +constexpr ImU32 kArrayGroupOutline = IM_COL32(255, 0, 0, 255); + class TableTemplateUI : public TemplateUI { private: @@ -38,9 +42,41 @@ private: }; std::vector<UICell> mUICells; + struct UIArrayGroup + { + ImVec2 Pos; + ImVec2 Size; + }; + std::vector<UIArrayGroup> mUIArrayGroups; + + /* Selection range */ Vec2i mSelectionTL; Vec2i mSelectionBR; + /* Selection states */ + union + { + /// "CS" stands for "Constant cell selection States" + struct + { + } mCS{}; // Initialize to this element + + /// "SS" stands for "Singular parameter selection States". + struct + { + bool ErrorDuplicateVarName; + bool HasLeftAG; + bool HasRightAG; + } mSS; + + /// "AS" stands for "Array group parameter selection States". + struct + { + bool ErrorDuplicateVarName; + } mAS; + }; + + /* Table states */ bool mDirty = false; bool mFirstDraw = true; @@ -75,15 +111,38 @@ public: { mTable->Resize(width, height); mUICells.resize(width * height); + mUIArrayGroups.resize(mTable->GetArrayGroupCount()); + + for (size_t i = 0; i < mUIArrayGroups.size(); ++i) { + auto& ag = mTable->GetArrayGroup(i); + auto& uag = mUIArrayGroups[i]; + + auto itemSpacing = ImGui::GetStyle().ItemSpacing; + uag.Pos.x = 0; + for (int x = 0; x < ag.LeftCell; ++x) { + uag.Pos.x += mTable->GetColumnWidth(x) + itemSpacing.x; + } + uag.Pos.y = 0; + for (int y = 0; y < ag.Row; ++y) { + uag.Pos.y += mTable->GetRowHeight(y) + itemSpacing.y; + } + + uag.Size.x = mTable->GetRowHeight(ag.Row); + uag.Size.y = 0; + for (int x = ag.LeftCell; x <= ag.RightCell; ++x) { + uag.Size.y += mTable->GetColumnWidth(x); + } + } } private: void DisplayInspector() { + // This is an id, no need to localize if (ImGui::BeginTabBar("Inspector")) { - if (ImGui::BeginTabItem("Cell")) { + if (ImGui::BeginTabItem(I18N_TEXT("Cell", L10N_TABLE_CELL))) { if (!IsSelected()) { - ImGui::Text("Select a cell to edit"); + ImGui::Text(I18N_TEXT("Select a cell to edit", L10N_TABLE_CELL_SELECT_MSG)); } else if (mSelectionTL == mSelectionBR) { auto& selectCell = mTable->GetCell(mSelectionTL); DisplayCellProperties(mSelectionTL); @@ -93,8 +152,8 @@ private: ImGui::EndTabItem(); } - if (ImGui::BeginTabItem("Table")) { - DisplayTableInspector(); + if (ImGui::BeginTabItem(I18N_TEXT("Table", L10N_TABLE))) { + DisplayTableProperties(); ImGui::EndTabItem(); } @@ -107,6 +166,36 @@ private: auto& cell = mTable->GetCell(pos); auto& uiCell = mUICells[pos.y * mTable->GetTableWidth() + pos.x]; + if (ImGui::Button(I18N_TEXT("Convert to...", L10N_TABLE_CELL_CONV))) { + ImGui::OpenPopup("ConvertCtxMenu"); + } + if (ImGui::BeginPopup("ConvertCtxMenu")) { + if (ImGui::MenuItem(I18N_TEXT("Single parameter", L10N_TABLE_CELL_CONV_PARAM))) { + mTable->SetCellType(pos, TableCell::SingularParametricCell); + } + + bool createDisabled = cell.Type == TableCell::ArrayParametricCell; + if (ImGui::MenuItemConditional(I18N_TEXT("Create array group", L10N_TABLE_CELL_CONV_CREATE_AG), createDisabled)) { + mTable->AddArrayGroup(pos.x, pos.x, pos.y); + } + + bool leftDisabled = !mSS.HasLeftAG || cell.Type == TableCell::ArrayParametricCell; + if (ImGui::MenuItemConditional(I18N_TEXT("Add to array group to the left", L10N_TABLE_CELL_CONV_ADD_AG_LEFT), leftDisabled)) { + auto& leftCell = mTable->GetCell((Vec2i){ pos.x - 1, pos.y }); + mTable->ExtendArrayGroupRight(leftCell.DataId, 1); + } + + bool rightDisabled = !mSS.HasRightAG || cell.Type == TableCell::ArrayParametricCell; + if (ImGui::MenuItemConditional(I18N_TEXT("Add to array group to the right", L10N_TABLE_CELL_CONV_ADD_AG_RIGHT), rightDisabled)) { + auto& rightCell = mTable->GetCell((Vec2i){ pos.x + 1, pos.y }); + mTable->ExtendArrayGroupLeft(rightCell.DataId, 1); + } + + ImGui::EndPopup(); + } + + ImGui::Spacing(); + constexpr auto kLeft = I18N_TEXT("Left", L10N_TABLE_CELL_ALIGN_LEFT); constexpr auto kCenter = I18N_TEXT("Center", L10N_TABLE_CELL_ALIGN_CENTER); constexpr auto kRight = I18N_TEXT("Right", L10N_TABLE_CELL_ALIGN_RIGHT); @@ -162,20 +251,31 @@ private: case TableCell::SingularParametricCell: if (ImGui::InputText(I18N_TEXT("Variable name", L10N_TABLE_CELL_VAR_NAME), &cell.Content)) { - // TODO validate if name is repeat + auto c = mTable->FindCell(cell.Content); + mSS.ErrorDuplicateVarName = c != nullptr; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip(I18N_TEXT("Name of the parameter link to this cell.", L10N_TABLE_CELL_VAR_TOOLTIP)); } + + if (mSS.ErrorDuplicateVarName) { + ImGui::ErrorMessage(I18N_TEXT("Variable name duplicated.", L10N_TABLE_CELL_VAR_NAME_DUP)); + } break; case TableCell::ArrayParametricCell: if (ImGui::InputText(I18N_TEXT("Variable name", L10N_TABLE_CELL_VAR_NAME), &cell.Content)) { - // TODO validate if name is repeat + auto ag = mTable->GetArrayGroup(cell.DataId); + auto cl = ag.FindCell(cell.Content); + mAS.ErrorDuplicateVarName = cl.x != -1 && cl.y != -1; } 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)); } + + if (mAS.ErrorDuplicateVarName) { + ImGui::ErrorMessage(I18N_TEXT("Variable name duplicated.", L10N_TABLE_CELL_VAR_NAME_DUP)); + } break; } } @@ -185,7 +285,7 @@ private: // TODO } - void DisplayTableInspector() + void DisplayTableProperties() { // TODO } @@ -193,6 +293,7 @@ private: void DisplayTable() { ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8, 8)); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(8, 8)); ImGui::BeginChild("TableTemplate"); auto regularColor = ImGui::GetColorU32(ImGuiCol_Button); @@ -222,7 +323,6 @@ private: window->DC.CursorPos + ImGui::CalcItemSize(size, 0.0f, 0.0f), }; - // TODO draw indicator for parameter cells /* Draw cell body */ if (uiCell.Selected) { @@ -242,6 +342,22 @@ private: window->DrawList->AddRectFilled(rect.Min, rect.Max, color); } + /* Draw cell type indicator */ + switch (cell.Type) { + // No indicator + case TableCell::ConstantCell: break; + + case TableCell::SingularParametricCell: + window->DrawList->AddRect( + rect.Min - ImVec2(1, 1), + rect.Max + ImVec2(1, 1), + kSingleParamOutline); + break; + + // Drawn separately in loop below + case TableCell::ArrayParametricCell: break; + } + /* Draw cell content */ auto content = cell.Content.c_str(); @@ -283,8 +399,15 @@ private: } } + for (auto& uag : mUIArrayGroups) { + ImGui::GetCurrentWindow()->DrawList->AddRect( + uag.Pos - ImVec2(1, 1), + uag.Pos + uag.Size + ImVec2(1, 1), + kArrayGroupOutline); + } + ImGui::EndChild(); - ImGui::PopStyleVar(); + ImGui::PopStyleVar(2); } template <class TFunction> @@ -314,6 +437,13 @@ private: mSelectionTL = { -1, -1 }; mSelectionBR = { -1, -1 }; + + ResetCS(); + } + + void ResetCS() + { + mCS = {}; } void SelectRange(Vec2i p1, Vec2i p2) @@ -334,6 +464,16 @@ private: auto& uiCell = mUICells[i]; uiCell.Selected = true; }); + + ResetAS(); + } + + void ResetSS(Vec2i pos) + { + mSS = {}; + mSS.ErrorDuplicateVarName = false; + mSS.HasLeftAG = pos.x >= 1; + mSS.HasRightAG = pos.x < mTable->GetTableWidth(); } void SelectCell(Vec2i cell) @@ -345,6 +485,14 @@ private: int i = cell.y * mTable->GetTableWidth() + cell.x; mUICells[i].Selected = true; + + ResetSS(cell); + } + + void ResetAS() + { + mAS = {}; + mAS.ErrorDuplicateVarName = false; } }; diff --git a/core/src/UI/UI_Utils.cpp b/core/src/UI/UI_Utils.cpp index e3ac097..0dcde8f 100644 --- a/core/src/UI/UI_Utils.cpp +++ b/core/src/UI/UI_Utils.cpp @@ -44,6 +44,15 @@ bool ImGui::Button(const char* label, const ImVec2& sizeArg, bool disabled) return res; } +bool ImGui::MenuItemConditional(const char* name, bool disabled) +{ + if (disabled) PushDisabled(); + bool res = MenuItem(name, nullptr, false, disabled); + if (disabled) PopDisabled(); + + return res; +} + void ImGui::ErrorIcon() { ImGui::PushStyleColor(ImGuiCol_Text, ImVec4{ 237 / 255.0f, 67 / 255.0f, 55 / 255.0f, 1.0f }); // #ED4337 |