diff --git a/lib/libimhex/include/hex/api/content_registry.hpp b/lib/libimhex/include/hex/api/content_registry.hpp index 99e52748e..16f8bd613 100644 --- a/lib/libimhex/include/hex/api/content_registry.hpp +++ b/lib/libimhex/include/hex/api/content_registry.hpp @@ -232,6 +232,11 @@ namespace hex { DrawCallback callback; }; + struct SidebarItem { + std::string icon; + DrawCallback callback; + }; + } u32 getDockSpaceId(); @@ -240,6 +245,7 @@ namespace hex { void addWelcomeScreenEntry(const impl::DrawCallback &function); void addFooterItem(const impl::DrawCallback &function); void addToolbarItem(const impl::DrawCallback &function); + void addSidebarItem(const std::string &icon, const impl::DrawCallback &function); void addLayout(const std::string &unlocalizedName, const impl::LayoutFunction &function); @@ -247,6 +253,7 @@ namespace hex { std::vector& getWelcomeScreenEntries(); std::vector& getFooterItems(); std::vector& getToolbarItems(); + std::vector& getSidebarItems(); std::vector& getLayouts(); } diff --git a/lib/libimhex/include/hex/helpers/shared_data.hpp b/lib/libimhex/include/hex/helpers/shared_data.hpp index 46d969bd0..3556ecdfa 100644 --- a/lib/libimhex/include/hex/helpers/shared_data.hpp +++ b/lib/libimhex/include/hex/helpers/shared_data.hpp @@ -81,6 +81,7 @@ namespace hex { static std::vector welcomeScreenEntries; static std::vector footerItems; static std::vector toolbarItems; + static std::vector sidebarItems; static std::vector layouts; static std::map> globalShortcuts; diff --git a/lib/libimhex/source/api/content_registry.cpp b/lib/libimhex/source/api/content_registry.cpp index 8d61a1444..b91da1ee0 100644 --- a/lib/libimhex/source/api/content_registry.cpp +++ b/lib/libimhex/source/api/content_registry.cpp @@ -312,6 +312,10 @@ namespace hex { getToolbarItems().push_back(function); } + void ContentRegistry::Interface::addSidebarItem(const std::string &icon, const impl::DrawCallback &function) { + getSidebarItems().push_back({ icon, function }); + } + void ContentRegistry::Interface::addLayout(const std::string &unlocalizedName, const impl::LayoutFunction &function) { log::info("Added new layout: {}", unlocalizedName); @@ -332,6 +336,9 @@ namespace hex { std::vector& ContentRegistry::Interface::getToolbarItems() { return SharedData::toolbarItems; } + std::vector& ContentRegistry::Interface::getSidebarItems() { + return SharedData::sidebarItems; + } std::vector& ContentRegistry::Interface::getLayouts() { return SharedData::layouts; diff --git a/lib/libimhex/source/helpers/shared_data.cpp b/lib/libimhex/source/helpers/shared_data.cpp index 310a9ff1c..ec06daa43 100644 --- a/lib/libimhex/source/helpers/shared_data.cpp +++ b/lib/libimhex/source/helpers/shared_data.cpp @@ -30,6 +30,7 @@ namespace hex { std::vector SharedData::mainMenuItems; std::vector SharedData::welcomeScreenEntries; std::vector SharedData::footerItems; + std::vector SharedData::sidebarItems; std::vector SharedData::toolbarItems; std::vector SharedData::layouts; diff --git a/main/source/window/window.cpp b/main/source/window/window.cpp index ebe536066..0f926c8b7 100644 --- a/main/source/window/window.cpp +++ b/main/source/window/window.cpp @@ -349,15 +349,26 @@ namespace hex { ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; if (ImGui::Begin("DockSpace", nullptr, windowFlags)) { + auto drawList = ImGui::GetWindowDrawList(); ImGui::PopStyleVar(); - SharedData::dockSpaceId = ImGui::DockSpace(ImGui::GetID("MainDock"), ImVec2(0.0f, ImGui::GetContentRegionAvail().y - ImGui::GetTextLineHeightWithSpacing() - ImGui::GetStyle().FramePadding.y * 2 - 1)); + auto sidebarPos = ImGui::GetCursorPos(); + auto sidebarWidth = ContentRegistry::Interface::getSidebarItems().empty() ? 0 : 30_scaled; + + ImGui::SetCursorPosX(sidebarWidth); + + auto footerHeight = ImGui::GetTextLineHeightWithSpacing() + ImGui::GetStyle().FramePadding.y * 2 + 1_scaled; + auto dockSpaceSize = ImVec2(SharedData::windowSize.x - sidebarWidth, ImGui::GetContentRegionAvail().y - footerHeight); + + SharedData::dockSpaceId = ImGui::DockSpace(ImGui::GetID("MainDock"), dockSpaceSize); + + drawList->AddRectFilled(ImGui::GetWindowPos(), ImGui::GetWindowPos() + ImGui::GetWindowSize() - ImVec2(dockSpaceSize.x, footerHeight - ImGui::GetStyle().FramePadding.y - 1_scaled), ImGui::GetColorU32(ImGuiCol_MenuBarBg)); ImGui::Separator(); ImGui::SetCursorPosX(8); for (const auto &callback : ContentRegistry::Interface::getFooterItems()) { - auto prevIdx = ImGui::GetWindowDrawList()->_VtxCurrentIdx; + auto prevIdx = drawList->_VtxCurrentIdx; callback(); - auto currIdx = ImGui::GetWindowDrawList()->_VtxCurrentIdx; + auto currIdx = drawList->_VtxCurrentIdx; // Only draw separator if something was actually drawn if (prevIdx != currIdx) { @@ -367,6 +378,51 @@ namespace hex { } } + { + ImGui::SetCursorPos(sidebarPos); + + static s32 openWindow = -1; + u32 index = 0; + ImGui::PushID("SideBarWindows"); + for (const auto &[icon, callback] : ContentRegistry::Interface::getSidebarItems()) { + ImGui::SetCursorPosY(sidebarPos.y + sidebarWidth * index); + + ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetColorU32(ImGuiCol_MenuBarBg)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImGui::GetColorU32(ImGuiCol_ScrollbarGrabActive)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::GetColorU32(ImGuiCol_ScrollbarGrabHovered)); + + ImGui::BeginDisabled(!ImHexApi::Provider::isValid()); + { + if (ImGui::Button(icon.c_str(), ImVec2(sidebarWidth, sidebarWidth))) { + if (openWindow == index) + openWindow = -1; + else + openWindow = index; + } + } + ImGui::EndDisabled(); + + ImGui::PopStyleColor(3); + + bool open = openWindow == index; + if (open) { + ImGui::SetNextWindowPos(ImGui::GetWindowPos() + sidebarPos + ImVec2(sidebarWidth - 2_scaled, 0)); + ImGui::SetNextWindowSize(ImVec2(250_scaled, dockSpaceSize.y + ImGui::GetStyle().FramePadding.y + 2_scaled)); + + ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1); + if (ImGui::Begin("Window", &open, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar)) { + callback(); + } + ImGui::End(); + ImGui::PopStyleVar(); + } + + ImGui::NewLine(); + index++; + } + ImGui::PopID(); + } + ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); if (ImGui::BeginMainMenuBar()) { @@ -420,6 +476,9 @@ namespace hex { } this->beginNativeWindowFrame(); + + drawList->AddLine(ImGui::GetWindowPos() + ImVec2(sidebarWidth - 2, 0), ImGui::GetWindowPos() + ImGui::GetWindowSize() - ImVec2(dockSpaceSize.x + 2, footerHeight - ImGui::GetStyle().FramePadding.y - 2), ImGui::GetColorU32(ImGuiCol_Separator)); + drawList->AddLine(ImGui::GetWindowPos() + ImVec2(sidebarWidth, ImGui::GetCurrentWindow()->MenuBarHeight()), ImGui::GetWindowPos() + ImVec2(ImGui::GetWindowSize().x, ImGui::GetCurrentWindow()->MenuBarHeight()), ImGui::GetColorU32(ImGuiCol_Separator)); } ImGui::End(); ImGui::PopStyleVar(2);