mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2025-01-05 15:57:11 +01:00
215 lines
7.5 KiB
C++
215 lines
7.5 KiB
C++
#include <gui/widgets/menu.h>
|
|
#include <imgui/imgui.h>
|
|
#include <imgui/imgui_internal.h>
|
|
#include <gui/style.h>
|
|
|
|
Menu::Menu() {
|
|
}
|
|
|
|
void Menu::registerEntry(std::string name, void (*drawHandler)(void* ctx), void* ctx, ModuleManager::Instance* inst) {
|
|
MenuItem_t item;
|
|
item.drawHandler = drawHandler;
|
|
item.ctx = ctx;
|
|
item.inst = inst;
|
|
items[name] = item;
|
|
if (!isInOrderList(name)) {
|
|
MenuOption_t opt;
|
|
opt.name = name;
|
|
opt.open = true;
|
|
order.push_back(opt);
|
|
}
|
|
}
|
|
|
|
void Menu::removeEntry(std::string name) {
|
|
items.erase(name);
|
|
}
|
|
|
|
bool Menu::draw(bool updateStates) {
|
|
bool changed = false;
|
|
float menuWidth = ImGui::GetContentRegionAvailWidth();
|
|
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
|
|
|
int displayedCount = 0;
|
|
int rawId = 0;
|
|
|
|
ImU32 textColor = ImGui::GetColorU32(ImGuiCol_Text);
|
|
|
|
for (MenuOption_t& opt : order) {
|
|
rawId++;
|
|
if (items.find(opt.name) == items.end()) {
|
|
continue;
|
|
}
|
|
if (opt.name == draggedMenuName) {
|
|
ImGui::BeginTooltip();
|
|
ImGui::Text("%s", draggedMenuName.c_str());
|
|
ImGui::EndTooltip();
|
|
continue;
|
|
}
|
|
|
|
if (displayedCount == insertBefore && !draggedMenuName.empty()) {
|
|
if (updateStates) { ImGui::SetNextItemOpen(false); }
|
|
ImVec2 posMin = ImGui::GetCursorScreenPos();
|
|
ImVec2 posMax = ImVec2(posMin.x + menuWidth, posMin.y + ImGui::GetFrameHeight());
|
|
style::beginDisabled();
|
|
ImRect orignalRect = window->WorkRect;
|
|
ImGui::CollapsingHeader((draggedMenuName + "##sdrpp_main_menu_dragging").c_str());
|
|
if (items[draggedOpt.name].inst != NULL) {
|
|
window->WorkRect = orignalRect;
|
|
ImVec2 pos = ImGui::GetCursorPos();
|
|
ImGui::SetCursorPosX(pos.x + menuWidth - ImGui::GetTextLineHeight() - 6);
|
|
ImGui::SetCursorPosY(pos.y - 10 - ImGui::GetTextLineHeight());
|
|
bool enabled = items[draggedOpt.name].inst->isEnabled();
|
|
ImGui::Checkbox(("##_menu_checkbox_" + draggedOpt.name).c_str(), &enabled);
|
|
ImGui::SetCursorPos(pos);
|
|
}
|
|
style::endDisabled();
|
|
window->DrawList->AddRect(posMin, posMax, textColor);
|
|
}
|
|
displayedCount++;
|
|
|
|
MenuItem_t& item = items[opt.name];
|
|
|
|
|
|
ImRect orginalRect = window->WorkRect;
|
|
if (item.inst != NULL) {
|
|
window->WorkRect = ImRect(orginalRect.Min, ImVec2(orginalRect.Max.x - ImGui::GetTextLineHeight() - 6, orginalRect.Max.y));
|
|
}
|
|
|
|
ImVec2 posMin = ImGui::GetCursorScreenPos();
|
|
ImVec2 posMax = ImVec2(posMin.x + menuWidth, posMin.y + ImGui::GetFrameHeight());
|
|
|
|
headerTops[displayedCount - 1] = posMin.y;
|
|
optionIDs[displayedCount - 1] = rawId - 1;
|
|
|
|
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && ImGui::IsMouseHoveringRect(posMin, posMax)) {
|
|
menuClicked = true;
|
|
clickedMenuName = opt.name;
|
|
}
|
|
|
|
if (menuClicked && ImGui::IsMouseDragging(ImGuiMouseButton_Left) && draggedMenuName.empty() && clickedMenuName == opt.name) {
|
|
draggedMenuName = opt.name;
|
|
draggedId = rawId - 1;
|
|
draggedOpt = opt;
|
|
continue;
|
|
}
|
|
|
|
if (updateStates) { ImGui::SetNextItemOpen(opt.open); }
|
|
if (ImGui::CollapsingHeader((opt.name + "##sdrpp_main_menu").c_str())) {
|
|
if (item.inst != NULL) {
|
|
window->WorkRect = orginalRect;
|
|
ImVec2 pos = ImGui::GetCursorPos();
|
|
ImGui::SetCursorPosX(pos.x + menuWidth - ImGui::GetTextLineHeight() - 6);
|
|
ImGui::SetCursorPosY(pos.y - 10 - ImGui::GetTextLineHeight());
|
|
bool enabled = item.inst->isEnabled();
|
|
if (ImGui::Checkbox(("##_menu_checkbox_" + opt.name).c_str(), &enabled)) {
|
|
enabled ? item.inst->enable() : item.inst->disable();
|
|
changed = true;
|
|
}
|
|
ImGui::SetCursorPos(pos);
|
|
}
|
|
|
|
// Check if the state changed
|
|
if (!opt.open && !updateStates) {
|
|
opt.open = true;
|
|
changed = true;
|
|
}
|
|
|
|
item.drawHandler(item.ctx);
|
|
ImGui::Spacing();
|
|
}
|
|
else if (item.inst != NULL) {
|
|
window->WorkRect = orginalRect;
|
|
ImVec2 pos = ImGui::GetCursorPos();
|
|
ImGui::SetCursorPosX(pos.x + menuWidth - ImGui::GetTextLineHeight() - 6);
|
|
ImGui::SetCursorPosY(pos.y - 10 - ImGui::GetTextLineHeight());
|
|
bool enabled = item.inst->isEnabled();
|
|
if (ImGui::Checkbox(("##_menu_checkbox_" + opt.name).c_str(), &enabled)) {
|
|
enabled ? item.inst->enable() : item.inst->disable();
|
|
changed = true;
|
|
}
|
|
ImGui::SetCursorPos(pos);
|
|
|
|
if (opt.open && !updateStates) {
|
|
opt.open = false;
|
|
changed = true;
|
|
}
|
|
}
|
|
else if (opt.open && !updateStates) {
|
|
opt.open = false;
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
if (!ImGui::IsMouseDown(ImGuiMouseButton_Left) && menuClicked) {
|
|
|
|
if (!draggedMenuName.empty()) {
|
|
// Move menu
|
|
order.erase(order.begin() + draggedId);
|
|
|
|
if (insertBefore == displayedCount) {
|
|
order.push_back(draggedOpt);
|
|
}
|
|
else if (insertBeforeName != "") {
|
|
int beforeId = 0;
|
|
for (int i = 0; i < order.size(); i++) {
|
|
if (order[i].name == insertBeforeName) {
|
|
beforeId = i;
|
|
break;
|
|
}
|
|
}
|
|
order.insert(order.begin() + beforeId, draggedOpt);
|
|
}
|
|
changed = true;
|
|
}
|
|
|
|
menuClicked = false;
|
|
draggedMenuName = "";
|
|
insertBeforeName = "";
|
|
insertBefore = -1;
|
|
}
|
|
|
|
|
|
if (insertBefore == displayedCount && !draggedMenuName.empty()) {
|
|
if (updateStates) { ImGui::SetNextItemOpen(false); }
|
|
ImVec2 posMin = ImGui::GetCursorScreenPos();
|
|
ImVec2 posMax = ImVec2(posMin.x + menuWidth, posMin.y + ImGui::GetFrameHeight());
|
|
style::beginDisabled();
|
|
ImRect orignalRect = window->WorkRect;
|
|
ImGui::CollapsingHeader((draggedMenuName + "##sdrpp_main_menu_dragging").c_str());
|
|
if (items[draggedOpt.name].inst != NULL) {
|
|
window->WorkRect = orignalRect;
|
|
ImVec2 pos = ImGui::GetCursorPos();
|
|
ImGui::SetCursorPosX(pos.x + menuWidth - ImGui::GetTextLineHeight() - 6);
|
|
ImGui::SetCursorPosY(pos.y - 10 - ImGui::GetTextLineHeight());
|
|
bool enabled = items[draggedOpt.name].inst->isEnabled();
|
|
ImGui::Checkbox(("##_menu_checkbox_" + draggedOpt.name).c_str(), &enabled);
|
|
ImGui::SetCursorPos(pos);
|
|
}
|
|
style::endDisabled();
|
|
window->DrawList->AddRect(posMin, posMax, textColor);
|
|
}
|
|
|
|
if (!draggedMenuName.empty()) {
|
|
insertBefore = displayedCount;
|
|
ImVec2 mPos = ImGui::GetMousePos();
|
|
for (int i = 0; i < displayedCount; i++) {
|
|
if (headerTops[i] > mPos.y) {
|
|
insertBefore = i;
|
|
insertBeforeName = order[optionIDs[i]].name;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return changed;
|
|
}
|
|
|
|
bool Menu::isInOrderList(std::string name) {
|
|
for (MenuOption_t opt : order) {
|
|
if (opt.name == name) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|