2021-08-29 14:18:45 +02:00
|
|
|
#include <hex/api/content_registry.hpp>
|
2022-10-21 12:01:28 +02:00
|
|
|
#include <hex/api/imhex_api.hpp>
|
2023-11-21 14:38:01 +01:00
|
|
|
#include <hex/api/localization_manager.hpp>
|
2023-12-26 00:22:47 +01:00
|
|
|
#include <hex/api/task_manager.hpp>
|
2021-06-07 18:13:54 +02:00
|
|
|
|
2022-05-27 20:42:07 +02:00
|
|
|
#include <hex/ui/view.hpp>
|
2021-08-29 22:15:18 +02:00
|
|
|
#include <hex/helpers/utils.hpp>
|
|
|
|
#include <hex/helpers/fmt.hpp>
|
2022-07-02 17:53:13 +02:00
|
|
|
#include <hex/helpers/logger.hpp>
|
2021-08-29 22:15:18 +02:00
|
|
|
|
2022-07-26 14:59:08 +02:00
|
|
|
#include <fonts/codicons_font.h>
|
2021-08-21 00:52:11 +02:00
|
|
|
#include <imgui.h>
|
|
|
|
#include <imgui_internal.h>
|
2023-12-20 13:42:42 +01:00
|
|
|
#include <implot.h>
|
2021-12-31 01:10:06 +01:00
|
|
|
#include <hex/ui/imgui_imhex_extensions.h>
|
2021-08-21 00:52:11 +02:00
|
|
|
|
2023-12-26 00:22:47 +01:00
|
|
|
#include <toasts/toast_notification.hpp>
|
2021-06-07 18:13:54 +02:00
|
|
|
|
2023-04-08 00:58:53 +02:00
|
|
|
namespace hex::plugin::builtin {
|
2022-07-02 17:53:13 +02:00
|
|
|
|
2023-05-25 09:26:40 +02:00
|
|
|
void addTitleBarButtons() {
|
2023-11-10 20:47:08 +01:00
|
|
|
#if defined(DEBUG)
|
|
|
|
ContentRegistry::Interface::addTitleBarButton(ICON_VS_DEBUG, "hex.builtin.title_bar_button.debug_build", []{
|
|
|
|
if (ImGui::GetIO().KeyCtrl) {
|
|
|
|
// Explicitly trigger a segfault by writing to an invalid memory location
|
|
|
|
// Used for debugging crashes
|
|
|
|
*reinterpret_cast<u8 *>(0x10) = 0x10;
|
|
|
|
std::unreachable();
|
|
|
|
} else if (ImGui::GetIO().KeyShift) {
|
|
|
|
// Explicitly trigger an abort by throwing an uncaught exception
|
|
|
|
// Used for debugging exception errors
|
|
|
|
throw std::runtime_error("Debug Error");
|
|
|
|
std::unreachable();
|
|
|
|
} else {
|
|
|
|
hex::openWebpage("https://imhex.werwolv.net/debug");
|
|
|
|
}
|
|
|
|
});
|
|
|
|
#endif
|
2023-05-25 09:26:40 +02:00
|
|
|
|
2023-06-26 08:54:30 +02:00
|
|
|
ContentRegistry::Interface::addTitleBarButton(ICON_VS_SMILEY, "hex.builtin.title_bar_button.feedback", []{
|
2023-05-25 09:26:40 +02:00
|
|
|
hex::openWebpage("https://github.com/WerWolv/ImHex/discussions/categories/feedback");
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-05-27 20:42:07 +02:00
|
|
|
static void drawGlobalPopups() {
|
2023-12-26 00:22:47 +01:00
|
|
|
// Task exception toast
|
2022-09-03 23:56:57 +02:00
|
|
|
for (const auto &task : TaskManager::getRunningTasks()) {
|
|
|
|
if (task->hadException()) {
|
2023-12-26 00:22:47 +01:00
|
|
|
ui::ToastError::open(hex::format("hex.builtin.popup.error.task_exception"_lang, Lang(task->getUnlocalizedName()), task->getExceptionMessage()));
|
2022-09-03 23:56:57 +02:00
|
|
|
task->clearException();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2022-05-27 20:42:07 +02:00
|
|
|
}
|
|
|
|
|
2024-01-10 23:46:50 +01:00
|
|
|
static bool s_drawDragDropOverlay = false;
|
|
|
|
static void drawDragNDropOverlay() {
|
|
|
|
if (!s_drawDragDropOverlay)
|
|
|
|
return;
|
|
|
|
|
|
|
|
auto drawList = ImGui::GetForegroundDrawList();
|
|
|
|
|
|
|
|
drawList->PushClipRectFullScreen();
|
|
|
|
{
|
|
|
|
const auto windowPos = ImHexApi::System::getMainWindowPosition();
|
|
|
|
const auto windowSize = ImHexApi::System::getMainWindowSize();
|
|
|
|
const auto center = windowPos + (windowSize / 2.0F) - scaled({ 0, 50 });
|
|
|
|
|
|
|
|
// Draw background
|
|
|
|
{
|
|
|
|
const ImVec2 margin = scaled({ 15, 15 });
|
|
|
|
drawList->AddRectFilled(windowPos, windowPos + windowSize, ImGui::GetColorU32(ImGuiCol_WindowBg, 200.0/255.0));
|
|
|
|
drawList->AddRect(windowPos + margin, (windowPos + windowSize) - margin, ImGuiExt::GetCustomColorU32(ImGuiCustomCol_Highlight), 10_scaled, ImDrawFlags_None, 7.5_scaled);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw drag n drop icon
|
|
|
|
{
|
|
|
|
const ImVec2 iconSize = scaled({ 64, 64 });
|
|
|
|
const auto offset = scaled({ 15, 15 });
|
|
|
|
const auto margin = scaled({ 20, 20 });
|
|
|
|
|
2024-01-11 10:20:39 +01:00
|
|
|
const auto text = "hex.builtin.drag_drop.text"_lang;
|
2024-01-10 23:46:50 +01:00
|
|
|
const auto textSize = ImGui::CalcTextSize(text);
|
|
|
|
|
|
|
|
drawList->AddShadowRect(center - ImVec2(textSize.x, iconSize.y + 40_scaled) / 2.0F - offset - margin, center + ImVec2(textSize.x, iconSize.y + 75_scaled) / 2.0F + offset + ImVec2(0, textSize.y) + margin, ImGui::GetColorU32(ImGuiCol_WindowShadow), 20_scaled, ImVec2(), ImDrawFlags_None, 10_scaled);
|
|
|
|
drawList->AddRectFilled(center - ImVec2(textSize.x, iconSize.y + 40_scaled) / 2.0F - offset - margin, center + ImVec2(textSize.x, iconSize.y + 75_scaled) / 2.0F + offset + ImVec2(0, textSize.y) + margin, ImGui::GetColorU32(ImGuiCol_MenuBarBg, 10), 1_scaled, ImDrawFlags_None);
|
|
|
|
drawList->AddRect(center - iconSize / 2.0F - offset, center + iconSize / 2.0F - offset, ImGui::GetColorU32(ImGuiCol_Text), 5_scaled, ImDrawFlags_None, 7.5_scaled);
|
|
|
|
drawList->AddRect(center - iconSize / 2.0F + offset, center + iconSize / 2.0F + offset, ImGui::GetColorU32(ImGuiCol_Text), 5_scaled, ImDrawFlags_None, 7.5_scaled);
|
|
|
|
|
|
|
|
drawList->AddText(center + ImVec2(-textSize.x / 2, 85_scaled), ImGui::GetColorU32(ImGuiCol_Text), text);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
drawList->PopClipRect();
|
|
|
|
}
|
|
|
|
|
2022-05-27 20:42:07 +02:00
|
|
|
void addGlobalUIItems() {
|
2023-12-08 10:29:44 +01:00
|
|
|
EventFrameEnd::subscribe(drawGlobalPopups);
|
2024-01-10 23:46:50 +01:00
|
|
|
EventFrameEnd::subscribe(drawDragNDropOverlay);
|
|
|
|
|
|
|
|
EventFileDragged::subscribe([](bool entered) {
|
|
|
|
s_drawDragDropOverlay = entered;
|
|
|
|
});
|
2022-05-27 20:42:07 +02:00
|
|
|
}
|
|
|
|
|
2021-06-07 18:13:54 +02:00
|
|
|
void addFooterItems() {
|
2021-12-13 22:58:23 +01:00
|
|
|
if (hex::isProcessElevated()) {
|
|
|
|
ContentRegistry::Interface::addFooterItem([] {
|
2023-11-25 19:11:14 +01:00
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, ImGuiExt::GetCustomColorU32(ImGuiCustomCol_Highlight));
|
2021-12-13 22:58:23 +01:00
|
|
|
ImGui::TextUnformatted(ICON_VS_SHIELD);
|
2023-11-25 19:11:14 +01:00
|
|
|
ImGui::PopStyleColor();
|
2021-12-13 22:58:23 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-09-05 22:37:28 +02:00
|
|
|
#if defined(DEBUG)
|
|
|
|
ContentRegistry::Interface::addFooterItem([] {
|
|
|
|
static float framerate = 0;
|
2023-11-16 22:24:06 +01:00
|
|
|
if (ImGuiExt::HasSecondPassed()) {
|
2022-09-05 22:37:28 +02:00
|
|
|
framerate = 1.0F / ImGui::GetIO().DeltaTime;
|
|
|
|
}
|
2021-06-07 18:13:54 +02:00
|
|
|
|
2023-11-25 16:07:33 +01:00
|
|
|
ImGuiExt::TextFormatted("FPS {0:3}.{1:02}", u32(framerate), u32(framerate * 100) % 100);
|
2023-12-20 13:42:42 +01:00
|
|
|
|
|
|
|
if (ImGui::IsItemHovered()) {
|
|
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2());
|
|
|
|
if (ImGui::BeginTooltip()) {
|
2023-12-25 23:23:19 +01:00
|
|
|
|
|
|
|
static u32 frameCount = 0;
|
|
|
|
static double largestFrameTime = 0;
|
2023-12-20 13:42:42 +01:00
|
|
|
if (ImPlot::BeginPlot("##frame_time_graph", scaled({ 200, 100 }), ImPlotFlags_CanvasOnly | ImPlotFlags_NoFrame | ImPlotFlags_NoInputs)) {
|
|
|
|
ImPlot::SetupAxes("", "", ImPlotAxisFlags_NoLabel | ImPlotAxisFlags_NoTickLabels, ImPlotAxisFlags_NoLabel | ImPlotAxisFlags_LockMin | ImPlotAxisFlags_AutoFit);
|
2023-12-25 23:23:19 +01:00
|
|
|
ImPlot::SetupAxisLimits(ImAxis_Y1, 0, largestFrameTime * 1.25F, ImPlotCond_Always);
|
2023-12-20 13:42:42 +01:00
|
|
|
ImPlot::SetupAxisFormat(ImAxis_Y1, [](double value, char* buff, int size, void*) -> int {
|
|
|
|
return snprintf(buff, size, "%dms", int(value * 1000.0));
|
|
|
|
}, nullptr);
|
2023-12-25 23:23:19 +01:00
|
|
|
ImPlot::SetupAxisTicks(ImAxis_Y1, 0, largestFrameTime * 1.25F, 3);
|
2023-12-20 13:42:42 +01:00
|
|
|
|
|
|
|
static std::vector<double> values(100);
|
|
|
|
|
|
|
|
values.push_back(ImHexApi::System::getLastFrameTime());
|
|
|
|
if (values.size() > 100)
|
|
|
|
values.erase(values.begin());
|
|
|
|
|
2023-12-25 23:23:19 +01:00
|
|
|
if (frameCount % 100 == 0)
|
|
|
|
largestFrameTime = *std::ranges::max_element(values);
|
|
|
|
frameCount += 1;
|
|
|
|
|
2023-12-20 13:42:42 +01:00
|
|
|
ImPlot::PlotLine("FPS", values.data(), values.size());
|
|
|
|
ImPlot::EndPlot();
|
|
|
|
}
|
|
|
|
ImGui::EndTooltip();
|
|
|
|
}
|
|
|
|
ImGui::PopStyleVar();
|
|
|
|
}
|
2022-09-05 22:37:28 +02:00
|
|
|
});
|
|
|
|
#endif
|
2021-12-16 23:48:52 +01:00
|
|
|
|
|
|
|
ContentRegistry::Interface::addFooterItem([] {
|
2023-05-02 20:35:30 +02:00
|
|
|
static bool shouldResetProgress = false;
|
|
|
|
|
2022-08-17 16:15:36 +02:00
|
|
|
auto taskCount = TaskManager::getRunningTaskCount();
|
|
|
|
if (taskCount > 0) {
|
2023-01-24 14:59:19 +01:00
|
|
|
const auto &tasks = TaskManager::getRunningTasks();
|
2023-11-23 13:19:50 +01:00
|
|
|
const auto &frontTask = tasks.front();
|
2021-12-16 23:48:52 +01:00
|
|
|
|
2023-12-06 11:04:35 +01:00
|
|
|
if (frontTask == nullptr)
|
|
|
|
return;
|
2023-01-14 14:21:16 +01:00
|
|
|
|
2023-12-28 22:14:45 +01:00
|
|
|
const auto progress = frontTask->getMaxValue() == 0 ? -1 : float(frontTask->getValue()) / float(frontTask->getMaxValue());
|
2023-12-06 11:04:35 +01:00
|
|
|
|
|
|
|
ImHexApi::System::setTaskBarProgress(ImHexApi::System::TaskProgressState::Progress, ImHexApi::System::TaskProgressType::Normal, u32(progress * 100));
|
2023-01-14 14:21:16 +01:00
|
|
|
|
2023-11-23 13:19:50 +01:00
|
|
|
const auto widgetStart = ImGui::GetCursorPos();
|
|
|
|
{
|
|
|
|
ImGuiExt::TextSpinner(hex::format("({})", taskCount).c_str());
|
|
|
|
ImGui::SameLine();
|
2023-12-18 10:14:07 +01:00
|
|
|
ImGuiExt::SmallProgressBar(progress, (ImGui::GetCurrentWindowRead()->MenuBarHeight() - 10_scaled) / 2.0);
|
2023-11-23 13:19:50 +01:00
|
|
|
ImGui::SameLine();
|
|
|
|
}
|
|
|
|
const auto widgetEnd = ImGui::GetCursorPos();
|
2022-08-17 16:15:36 +02:00
|
|
|
|
|
|
|
ImGui::SetCursorPos(widgetStart);
|
2023-12-28 22:14:45 +01:00
|
|
|
ImGui::InvisibleButton("RestTasks", ImVec2(widgetEnd.x - widgetStart.x, ImGui::GetCurrentWindowRead()->MenuBarHeight()));
|
2022-08-17 16:15:36 +02:00
|
|
|
ImGui::SetCursorPos(widgetEnd);
|
|
|
|
|
2024-01-27 11:02:14 +01:00
|
|
|
std::string progressString;
|
|
|
|
if (progress < 0)
|
|
|
|
progressString = "";
|
|
|
|
else
|
2024-02-11 19:29:02 +01:00
|
|
|
progressString = hex::format("[ {}/{} ({:.1f}%) ] ", frontTask->getValue(), frontTask->getMaxValue(), std::min(progress, 1.0F) * 100.0F);
|
2024-01-27 11:02:14 +01:00
|
|
|
|
|
|
|
ImGuiExt::InfoTooltip(hex::format("{}{}", progressString, Lang(frontTask->getUnlocalizedName())).c_str());
|
2022-08-17 16:15:36 +02:00
|
|
|
|
2023-12-28 22:14:45 +01:00
|
|
|
if (ImGui::BeginPopupContextItem("RestTasks", ImGuiPopupFlags_MouseButtonLeft)) {
|
2022-08-17 16:15:36 +02:00
|
|
|
for (const auto &task : tasks) {
|
2022-10-04 23:37:48 +02:00
|
|
|
if (task->isBackgroundTask())
|
|
|
|
continue;
|
|
|
|
|
2022-08-17 16:15:36 +02:00
|
|
|
ImGui::PushID(&task);
|
2023-11-21 14:38:01 +01:00
|
|
|
ImGuiExt::TextFormatted("{}", Lang(task->getUnlocalizedName()));
|
2022-08-17 16:15:36 +02:00
|
|
|
ImGui::SameLine();
|
|
|
|
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
|
|
|
|
ImGui::SameLine();
|
2023-12-28 22:14:45 +01:00
|
|
|
ImGuiExt::SmallProgressBar(task->getMaxValue() == 0 ? -1 : (float(task->getValue()) / float(task->getMaxValue())), (ImGui::GetTextLineHeightWithSpacing() - 5_scaled) / 2);
|
2022-08-17 16:15:36 +02:00
|
|
|
ImGui::SameLine();
|
|
|
|
|
|
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
|
2023-11-16 22:24:06 +01:00
|
|
|
if (ImGuiExt::ToolBarButton(ICON_VS_DEBUG_STOP, ImGui::GetStyleColorVec4(ImGuiCol_Text)))
|
2022-08-17 16:15:36 +02:00
|
|
|
task->interrupt();
|
|
|
|
ImGui::PopStyleVar();
|
|
|
|
|
|
|
|
ImGui::PopID();
|
|
|
|
}
|
|
|
|
ImGui::EndPopup();
|
|
|
|
}
|
2021-12-16 23:48:52 +01:00
|
|
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
2022-08-17 16:15:36 +02:00
|
|
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, scaled(ImVec2(1, 2)));
|
2023-11-16 22:24:06 +01:00
|
|
|
if (ImGuiExt::ToolBarButton(ICON_VS_DEBUG_STOP, ImGui::GetStyleColorVec4(ImGuiCol_Text)))
|
2022-08-17 16:15:36 +02:00
|
|
|
frontTask->interrupt();
|
|
|
|
ImGui::PopStyleVar();
|
2023-05-02 20:35:30 +02:00
|
|
|
|
|
|
|
shouldResetProgress = true;
|
2023-01-14 14:21:16 +01:00
|
|
|
} else {
|
2023-05-02 20:35:30 +02:00
|
|
|
if (shouldResetProgress) {
|
|
|
|
ImHexApi::System::setTaskBarProgress(ImHexApi::System::TaskProgressState::Reset, ImHexApi::System::TaskProgressType::Normal, 0);
|
|
|
|
shouldResetProgress = false;
|
|
|
|
}
|
2021-12-16 23:48:52 +01:00
|
|
|
}
|
2021-06-07 18:13:54 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2023-12-18 11:46:23 +01:00
|
|
|
static void drawProviderContextMenu(prv::Provider *provider) {
|
|
|
|
for (const auto &menuEntry : provider->getMenuEntries()) {
|
|
|
|
if (ImGui::MenuItem(menuEntry.name.c_str())) {
|
|
|
|
menuEntry.callback();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-21 18:39:32 +01:00
|
|
|
struct MenuItemSorter {
|
|
|
|
bool operator()(const auto *a, const auto *b) const {
|
|
|
|
return a->toolbarIndex < b->toolbarIndex;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-08-21 00:52:11 +02:00
|
|
|
void addToolbarItems() {
|
2023-11-17 14:46:21 +01:00
|
|
|
ShortcutManager::addGlobalShortcut(AllowWhileTyping + ALT + CTRLCMD + Keys::Left, "hex.builtin.shortcut.prev_provider", []{
|
2023-09-24 18:04:14 +02:00
|
|
|
auto currIndex = ImHexApi::Provider::getCurrentProviderIndex();
|
|
|
|
|
|
|
|
if (currIndex > 0)
|
|
|
|
ImHexApi::Provider::setCurrentProvider(currIndex - 1);
|
|
|
|
});
|
|
|
|
|
2023-11-17 14:46:21 +01:00
|
|
|
ShortcutManager::addGlobalShortcut(AllowWhileTyping + ALT + CTRLCMD + Keys::Right, "hex.builtin.shortcut.next_provider", []{
|
2023-09-24 18:04:14 +02:00
|
|
|
auto currIndex = ImHexApi::Provider::getCurrentProviderIndex();
|
|
|
|
|
|
|
|
const auto &providers = ImHexApi::Provider::getProviders();
|
|
|
|
if (currIndex < i64(providers.size() - 1))
|
|
|
|
ImHexApi::Provider::setCurrentProvider(currIndex + 1);
|
|
|
|
});
|
|
|
|
|
2023-10-24 19:29:22 +02:00
|
|
|
static bool providerJustChanged = true;
|
2023-12-08 10:29:44 +01:00
|
|
|
EventProviderChanged::subscribe([](auto, auto) { providerJustChanged = true; });
|
2023-10-24 19:29:22 +02:00
|
|
|
|
2023-12-18 11:46:23 +01:00
|
|
|
static prv::Provider *rightClickedProvider = nullptr;
|
|
|
|
EventSearchBoxClicked::subscribe([](ImGuiMouseButton button){
|
|
|
|
if (button == ImGuiMouseButton_Right) {
|
|
|
|
rightClickedProvider = ImHexApi::Provider::get();
|
|
|
|
RequestOpenPopup::post("ProviderMenu");
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
EventFrameBegin::subscribe([] {
|
2023-12-18 22:51:08 +01:00
|
|
|
if (rightClickedProvider != nullptr && !rightClickedProvider->getMenuEntries().empty()) {
|
|
|
|
if (ImGui::BeginPopup("ProviderMenu")) {
|
2023-12-18 22:45:15 +01:00
|
|
|
drawProviderContextMenu(rightClickedProvider);
|
2023-12-18 22:51:08 +01:00
|
|
|
ImGui::EndPopup();
|
|
|
|
}
|
2023-12-18 22:45:15 +01:00
|
|
|
}
|
2023-12-18 11:46:23 +01:00
|
|
|
});
|
|
|
|
|
2023-12-18 22:51:08 +01:00
|
|
|
EventProviderChanged::subscribe([](auto, auto){
|
|
|
|
rightClickedProvider = nullptr;
|
|
|
|
});
|
|
|
|
|
2024-01-30 00:11:45 +01:00
|
|
|
static bool alwaysShowProviderTabs = false;
|
2024-02-18 11:29:18 +01:00
|
|
|
ContentRegistry::Settings::onChange("hex.builtin.setting.interface", "hex.builtin.setting.interface.always_show_provider_tabs", [](const ContentRegistry::Settings::SettingsValue &value) {
|
|
|
|
alwaysShowProviderTabs = value.get<bool>(false);
|
2024-01-30 00:11:45 +01:00
|
|
|
});
|
|
|
|
|
2021-08-21 00:52:11 +02:00
|
|
|
ContentRegistry::Interface::addToolbarItem([] {
|
2024-01-21 18:39:32 +01:00
|
|
|
std::set<const ContentRegistry::Interface::impl::MenuItem*, MenuItemSorter> menuItems;
|
2021-08-21 00:52:11 +02:00
|
|
|
|
2024-01-21 18:39:32 +01:00
|
|
|
for (const auto &[priority, menuItem] : ContentRegistry::Interface::impl::getMenuItems()) {
|
|
|
|
if (menuItem.toolbarIndex != -1) {
|
|
|
|
menuItems.insert(&menuItem);
|
2022-10-21 12:01:28 +02:00
|
|
|
}
|
2022-05-27 20:42:07 +02:00
|
|
|
}
|
2021-08-21 13:53:50 +02:00
|
|
|
|
2024-01-21 18:39:32 +01:00
|
|
|
for (const auto &menuItem : menuItems) {
|
|
|
|
if (menuItem->unlocalizedNames.back().get() == ContentRegistry::Interface::impl::SeparatorValue) {
|
|
|
|
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
|
|
|
|
continue;
|
|
|
|
}
|
2021-08-21 13:53:50 +02:00
|
|
|
|
2024-01-21 18:39:32 +01:00
|
|
|
ImGui::BeginDisabled(!menuItem->enabledCallback());
|
|
|
|
if (ImGuiExt::ToolBarButton(menuItem->icon.glyph.c_str(), ImGuiExt::GetCustomColorVec4(ImGuiCustomCol(menuItem->icon.color)))) {
|
|
|
|
menuItem->callback();
|
2021-08-21 13:53:50 +02:00
|
|
|
}
|
2024-01-21 18:39:32 +01:00
|
|
|
ImGui::EndDisabled();
|
2022-05-27 20:42:07 +02:00
|
|
|
}
|
2024-01-21 18:39:32 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
// Provider switcher
|
|
|
|
ContentRegistry::Interface::addToolbarItem([] {
|
|
|
|
const auto provider = ImHexApi::Provider::get();
|
|
|
|
const bool providerValid = provider != nullptr;
|
|
|
|
const bool tasksRunning = TaskManager::getRunningTaskCount() > 0;
|
2021-09-21 02:29:54 +02:00
|
|
|
|
|
|
|
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
|
|
|
|
ImGui::Spacing();
|
2022-07-30 21:25:18 +02:00
|
|
|
ImGui::Spacing();
|
|
|
|
ImGui::Spacing();
|
2021-09-21 02:29:54 +02:00
|
|
|
|
2022-07-29 11:35:29 +02:00
|
|
|
ImGui::BeginDisabled(!providerValid || tasksRunning);
|
2022-05-27 20:42:07 +02:00
|
|
|
{
|
2024-02-10 23:31:05 +01:00
|
|
|
auto providers = ImHexApi::Provider::getProviders();
|
2021-09-21 02:29:54 +02:00
|
|
|
|
2022-07-30 21:25:18 +02:00
|
|
|
ImGui::PushStyleColor(ImGuiCol_TabActive, ImGui::GetColorU32(ImGuiCol_MenuBarBg));
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_TabUnfocusedActive, ImGui::GetColorU32(ImGuiCol_MenuBarBg));
|
2022-07-31 11:09:20 +02:00
|
|
|
auto providerSelectorVisible = ImGui::BeginTabBar("provider_switcher", ImGuiTabBarFlags_FittingPolicyScroll | ImGuiTabBarFlags_Reorderable | ImGuiTabBarFlags_AutoSelectNewTabs);
|
2022-07-30 21:25:18 +02:00
|
|
|
ImGui::PopStyleColor(2);
|
2021-09-21 02:29:54 +02:00
|
|
|
|
2022-07-30 21:25:18 +02:00
|
|
|
if (providerSelectorVisible) {
|
2022-03-27 00:01:28 +01:00
|
|
|
for (size_t i = 0; i < providers.size(); i++) {
|
2024-01-30 00:11:45 +01:00
|
|
|
if (providers.size() == 1 && !alwaysShowProviderTabs)
|
2023-12-07 11:21:13 +01:00
|
|
|
break;
|
|
|
|
|
2022-07-31 10:55:10 +02:00
|
|
|
auto &tabProvider = providers[i];
|
2023-09-24 18:04:14 +02:00
|
|
|
const auto selectedProviderIndex = ImHexApi::Provider::getCurrentProviderIndex();
|
2022-07-31 10:55:10 +02:00
|
|
|
|
2022-07-30 21:25:18 +02:00
|
|
|
bool open = true;
|
2022-07-31 10:55:10 +02:00
|
|
|
ImGui::PushID(tabProvider);
|
2023-09-24 18:04:14 +02:00
|
|
|
|
|
|
|
ImGuiTabItemFlags flags = ImGuiTabItemFlags_NoTooltip;
|
|
|
|
if (tabProvider->isDirty())
|
|
|
|
flags |= ImGuiTabItemFlags_UnsavedDocument;
|
2023-10-24 19:29:22 +02:00
|
|
|
if (i64(i) == selectedProviderIndex && providerJustChanged) {
|
2023-09-24 18:04:14 +02:00
|
|
|
flags |= ImGuiTabItemFlags_SetSelected;
|
2023-10-24 19:29:22 +02:00
|
|
|
providerJustChanged = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static size_t lastSelectedProvider = 0;
|
2023-09-24 18:04:14 +02:00
|
|
|
|
2023-10-24 19:29:22 +02:00
|
|
|
bool isSelected = false;
|
2023-09-24 18:04:14 +02:00
|
|
|
if (ImGui::BeginTabItem(tabProvider->getName().c_str(), &open, flags)) {
|
2023-10-24 19:29:22 +02:00
|
|
|
isSelected = true;
|
2022-07-30 21:25:18 +02:00
|
|
|
ImGui::EndTabItem();
|
2021-09-21 02:29:54 +02:00
|
|
|
}
|
2023-10-24 19:29:22 +02:00
|
|
|
|
|
|
|
if (isSelected && lastSelectedProvider != i) {
|
2023-09-24 18:04:14 +02:00
|
|
|
ImHexApi::Provider::setCurrentProvider(i);
|
2023-10-24 19:29:22 +02:00
|
|
|
lastSelectedProvider = i;
|
|
|
|
}
|
2023-06-02 14:44:19 +02:00
|
|
|
|
2023-11-16 22:24:06 +01:00
|
|
|
if (ImGuiExt::InfoTooltip()) {
|
2023-06-02 14:44:19 +02:00
|
|
|
ImGui::BeginTooltip();
|
|
|
|
|
2023-11-16 22:24:06 +01:00
|
|
|
ImGuiExt::TextFormatted("{}", tabProvider->getName().c_str());
|
2023-06-02 14:44:19 +02:00
|
|
|
|
2023-10-12 20:28:02 +02:00
|
|
|
const auto &description = tabProvider->getDataDescription();
|
2023-06-30 22:28:37 +02:00
|
|
|
if (!description.empty()) {
|
2023-06-02 14:44:19 +02:00
|
|
|
ImGui::Separator();
|
2023-06-30 22:28:37 +02:00
|
|
|
if (ImGui::GetIO().KeyShift && !description.empty()) {
|
2023-06-02 14:44:19 +02:00
|
|
|
|
2023-06-30 22:28:37 +02:00
|
|
|
if (ImGui::BeginTable("information", 2, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoKeepColumnsVisible, ImVec2(400_scaled, 0))) {
|
|
|
|
ImGui::TableSetupColumn("type");
|
|
|
|
ImGui::TableSetupColumn("value", ImGuiTableColumnFlags_WidthStretch);
|
2023-06-02 14:44:19 +02:00
|
|
|
|
2023-06-30 22:28:37 +02:00
|
|
|
ImGui::TableNextRow();
|
2023-06-02 14:44:19 +02:00
|
|
|
|
2023-06-30 22:28:37 +02:00
|
|
|
for (auto &[name, value] : description) {
|
|
|
|
ImGui::TableNextColumn();
|
2023-11-16 22:24:06 +01:00
|
|
|
ImGuiExt::TextFormatted("{}", name);
|
2023-06-30 22:28:37 +02:00
|
|
|
ImGui::TableNextColumn();
|
2023-11-16 22:24:06 +01:00
|
|
|
ImGuiExt::TextFormattedWrapped("{}", value);
|
2023-06-30 22:28:37 +02:00
|
|
|
}
|
2023-06-02 14:44:19 +02:00
|
|
|
|
2023-06-30 22:28:37 +02:00
|
|
|
ImGui::EndTable();
|
|
|
|
}
|
|
|
|
} else {
|
2023-11-16 22:24:06 +01:00
|
|
|
ImGuiExt::TextFormattedDisabled("hex.builtin.provider.tooltip.show_more"_lang);
|
2023-06-02 14:44:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndTooltip();
|
|
|
|
}
|
|
|
|
|
2022-07-31 10:55:10 +02:00
|
|
|
ImGui::PopID();
|
2021-09-21 02:29:54 +02:00
|
|
|
|
2022-07-30 21:25:18 +02:00
|
|
|
if (!open) {
|
|
|
|
ImHexApi::Provider::remove(providers[i]);
|
|
|
|
break;
|
|
|
|
}
|
2023-05-21 13:21:53 +02:00
|
|
|
|
2023-12-18 11:58:31 +01:00
|
|
|
if (ImGui::IsMouseReleased(ImGuiMouseButton_Right) && ImGui::IsItemHovered()) {
|
|
|
|
rightClickedProvider = tabProvider;
|
|
|
|
RequestOpenPopup::post("ProviderMenu");
|
2023-05-21 13:21:53 +02:00
|
|
|
}
|
2022-07-30 21:25:18 +02:00
|
|
|
}
|
|
|
|
ImGui::EndTabBar();
|
2021-09-21 02:29:54 +02:00
|
|
|
}
|
2022-05-27 20:42:07 +02:00
|
|
|
}
|
|
|
|
ImGui::EndDisabled();
|
2021-08-21 00:52:11 +02:00
|
|
|
});
|
2024-01-21 18:39:32 +01:00
|
|
|
|
|
|
|
ContentRegistry::Interface::addMenuItemToToolbar("hex.builtin.menu.edit.undo", ImGuiCustomCol_ToolbarBlue);
|
|
|
|
ContentRegistry::Interface::addMenuItemToToolbar("hex.builtin.menu.edit.redo", ImGuiCustomCol_ToolbarBlue);
|
|
|
|
ContentRegistry::Interface::addMenuItemToToolbar("hex.builtin.menu.file.create_file", ImGuiCustomCol_ToolbarGray);
|
|
|
|
ContentRegistry::Interface::addMenuItemToToolbar("hex.builtin.menu.file.open_file", ImGuiCustomCol_ToolbarBrown);
|
|
|
|
ContentRegistry::Interface::addMenuItemToToolbar("hex.builtin.view.hex_editor.menu.file.save", ImGuiCustomCol_ToolbarBlue);
|
|
|
|
ContentRegistry::Interface::addMenuItemToToolbar("hex.builtin.view.hex_editor.menu.file.save_as", ImGuiCustomCol_ToolbarBlue);
|
|
|
|
ContentRegistry::Interface::addMenuItemToToolbar("hex.builtin.menu.edit.bookmark.create", ImGuiCustomCol_ToolbarGreen);
|
2021-08-21 00:52:11 +02:00
|
|
|
}
|
|
|
|
|
2021-06-07 18:13:54 +02:00
|
|
|
}
|