#include "UI.hpp" #include #include #include #include #include #include namespace CPLT_UNITY_ID { enum class ActionResult { Confirmed, Canceled, Pending, }; /// \param list Item list that the item is in. /// \param item A non-null pointer to the currently being edited item. It should not change until this function returns a non-\c ActionResult::Pending value. template ActionResult ItemEditor(ItemList& list, T* item) { constexpr bool kHasDescription = requires(T t) { t.GetDescription(); }; constexpr bool kHasEmail = requires(T t) { t.GetEmail(); }; static bool duplicateName = false; static std::string name; static std::string description; static std::string email; if (name.empty()) { name = item->GetName(); if constexpr (kHasDescription) description = item->GetDescription(); if constexpr (kHasEmail) email = item->GetEmail(); } auto ClearStates = [&]() { duplicateName = false; name = {}; description = {}; }; if (ImGui::InputText(I18N_TEXT("Name", L10N_ITEM_COLUMN_NAME), &name)) { duplicateName = name != item->GetName() && list.Find(name) != nullptr; } if constexpr (kHasDescription) ImGui::InputText(I18N_TEXT("Description", L10N_ITEM_COLUMN_DESCRIPTION), &description); if constexpr (kHasEmail) ImGui::InputText(I18N_TEXT("Email", L10N_ITEM_COLUMN_EMAIL), &email); if (name.empty()) { ImGui::ErrorMessage(I18N_TEXT("Name cannot be empty", L10N_EMPTY_NAME_ERROR)); } if (duplicateName) { ImGui::ErrorMessage(I18N_TEXT("Duplicate name", L10N_DUPLICATE_NAME_ERROR)); } // Return Value auto rv = ActionResult::Pending; if (ImGui::Button(I18N_TEXT("Confirm", L10N_CONFIRM), name.empty() || duplicateName)) { if (item->GetName() != name) { item->SetName(std::move(name)); } if constexpr (kHasDescription) if (item->GetDescription() != description) { item->SetDescription(std::move(description)); } if constexpr (kHasEmail) if (item->GetEmail() != email) { item->SetEmail(std::move(email)); } ImGui::CloseCurrentPopup(); ClearStates(); rv = ActionResult::Confirmed; } ImGui::SameLine(); if (ImGui::Button(I18N_TEXT("Cancel", L10N_CANCEL))) { ImGui::CloseCurrentPopup(); ClearStates(); rv = ActionResult::Canceled; } return rv; } template void ItemListEntries(ItemList& list, int& selectedIdx) { constexpr bool kHasDescription = requires(T t) { t.GetDescription(); }; constexpr bool kHasEmail = requires(T t) { t.GetEmail(); }; constexpr bool kHasStock = requires(T t) { t.GetPrice(); }; constexpr bool kHasPrice = requires(T t) { t.GetPrice(); }; constexpr int kColumns = 1 /* Name column */ + kHasDescription + kHasEmail + kHasStock + kHasPrice; if (ImGui::BeginTable("", kColumns, ImGuiTableFlags_Borders)) { ImGui::TableSetupColumn(I18N_TEXT("Name", L10N_ITEM_COLUMN_NAME)); if constexpr (kHasDescription) ImGui::TableSetupColumn(I18N_TEXT("Description", L10N_ITEM_COLUMN_DESCRIPTION)); if constexpr (kHasEmail) ImGui::TableSetupColumn(I18N_TEXT("Email", L10N_ITEM_COLUMN_EMAIL)); if constexpr (kHasStock) ImGui::TableSetupColumn(I18N_TEXT("Stock", L10N_ITEM_COLUMN_STOCK)); if constexpr (kHasPrice) ImGui::TableSetupColumn(I18N_TEXT("Price", L10N_ITEM_COLUMN_PRICE)); ImGui::TableHeadersRow(); size_t idx = 0; for (auto& entry : list) { if (entry.IsInvalid()) { continue; } ImGui::TableNextRow(); ImGui::TableNextColumn(); if (ImGui::Selectable(entry.GetName().c_str(), selectedIdx == idx, ImGuiSelectableFlags_SpanAllColumns)) { selectedIdx = idx; } if constexpr (kHasDescription) { ImGui::TableNextColumn(); ImGui::TextUnformatted(entry.GetDescription().c_str()); } if constexpr (kHasEmail) { ImGui::TableNextColumn(); ImGui::TextUnformatted(entry.GetEmail().c_str()); } if constexpr (kHasStock) { ImGui::TableNextColumn(); ImGui::Text("%d", entry.GetStock()); } if constexpr (kHasPrice) { ImGui::TableNextColumn(); // TODO format in dollars ImGui::Text("%d", entry.GetPrice()); } idx++; } ImGui::EndTable(); } } template void ItemListEditor(ItemList& list) { bool opened = true; static int selectedIdx = -1; static T* editingItem = nullptr; if (ImGui::Button(ICON_FA_PLUS " " I18N_TEXT("Add", L10N_ADD))) { ImGui::SetNextWindowCentered(); ImGui::OpenPopup(I18N_TEXT("Add item", L10N_ITEM_ADD_DIALOG_TITLE)); editingItem = &list.Insert(""); } if (ImGui::BeginPopupModal(I18N_TEXT("Add item", L10N_ITEM_ADD_DIALOG_TITLE), &opened, ImGuiWindowFlags_AlwaysAutoResize)) { switch (ItemEditor(list, editingItem)) { case ActionResult::Confirmed: editingItem = nullptr; break; case ActionResult::Canceled: list.Remove(editingItem->GetId()); editingItem = nullptr; break; default: break; } ImGui::EndPopup(); } ImGui::SameLine(); if (ImGui::Button(ICON_FA_EDIT " " I18N_TEXT("Edit", L10N_EDIT), selectedIdx == -1)) { ImGui::SetNextWindowCentered(); ImGui::OpenPopup(I18N_TEXT("Edit item", L10N_ITEM_EDIT_DIALOG_TITLE)); editingItem = list.Find(selectedIdx); } if (ImGui::BeginPopupModal(I18N_TEXT("Edit item", L10N_ITEM_EDIT_DIALOG_TITLE), &opened, ImGuiWindowFlags_AlwaysAutoResize)) { if (ItemEditor(list, editingItem) != ActionResult::Pending) { editingItem = nullptr; } ImGui::EndPopup(); } ImGui::SameLine(); if (ImGui::Button(ICON_FA_TRASH " " I18N_TEXT("Delete", L10N_DELETE), selectedIdx == -1)) { ImGui::SetNextWindowCentered(); ImGui::OpenPopup(I18N_TEXT("Delete item", L10N_ITEM_DELETE_DIALOG_TITLE)); list.Remove(selectedIdx); } if (ImGui::BeginPopupModal(I18N_TEXT("Delete item", L10N_ITEM_DELETE_DIALOG_TITLE), &opened, ImGuiWindowFlags_AlwaysAutoResize)) { ImGui::TextUnformatted(I18N_TEXT("Are you sure you want to delete this item?", L10N_ITEM_DELETE_DIALOG_MESSAGE)); if (ImGui::Button(I18N_TEXT("Confirm", L10N_CONFIRM))) { ImGui::CloseCurrentPopup(); } ImGui::SameLine(); if (ImGui::Button(I18N_TEXT("Cancel", L10N_CANCEL))) { ImGui::CloseCurrentPopup(); } ImGui::EndPopup(); } ItemListEntries(list, selectedIdx); } } // namespace CPLT_UNITY_ID void UI::ItemsTab() { auto& gs = GlobalStates::GetInstance(); if (ImGui::BeginTabBar("ItemViewTabs")) { if (ImGui::BeginTabItem(I18N_TEXT("Products", L10N_ITEM_CATEGORY_PRODUCT))) { CPLT_UNITY_ID::ItemListEditor(gs.GetCurrentProject()->Products); ImGui::EndTabItem(); } if (ImGui::BeginTabItem(I18N_TEXT("Factories", L10N_ITEM_CATEGORY_FACTORY))) { CPLT_UNITY_ID::ItemListEditor(gs.GetCurrentProject()->Factories); ImGui::EndTabItem(); } if (ImGui::BeginTabItem(I18N_TEXT("Customers", L10N_ITEM_CATEGORY_CUSTOMER))) { CPLT_UNITY_ID::ItemListEditor(gs.GetCurrentProject()->Customers); ImGui::EndTabItem(); } ImGui::EndTabBar(); } }