1
0
mirror of synced 2024-12-02 03:07:18 +01:00
ImHex/lib/libimhex/source/ui/imgui_imhex_extensions.cpp
paxcut 3e4c4430d5
feat: Greatly improved the IEEE754 tool (#1047)
I just realized one feature request existed about this tool and have
added a comment to it referring this pr. Errors and additions are
described in the fork commit already. I'm not sure if I should repeat
them here again. I have tested the changes thoroughly, but it is always
possible some fringe case was not tested and is incorrect. The tests
were done using the many similar online calculators for IEEE 754
floating point formats.
IEEE 745 floating point tool redesign modeled after 'float toy' web app
(http://evanw.github.io/float-toy/)

Streamlined output using colors and compact layout which can be further
simplified.
Chosen display mode (detailed or simplified) is automatically saved and
set on new sessions.
Edit the binary bits, the integer hexadecimal or the floating point
decimal values and the entire app will update with the change.
Supports the main IEEE745 standard formats (half, single and double
precision) together with custom formats of size <= 64 bits.
Each format choice uses and displays the number of significant decimal
digits defined by the mantissa size.
Added labels to identify the location of each bit box inside the binary
representation.
Satisfies round trip / idempotent (reproducing) conversion property
Added theme colors, radio buttons for display mode and a clear button
that resets the tool.
Removed previously and incorrectly added locale translation to various
labels and languages
Attempted to adhere to code style formatting using existing code as
example.
An effort was made to use preferred variable types and functions from
std namespace when appropriate.
Attempted to document code using comments. 

Not implemented / left to complete at an later time

Arbitrary width and precision formats. 
Extended precision formats.
Shortest string property.
hexadecimal floating point display and conversions.
2023-05-19 21:18:38 +02:00

767 lines
32 KiB
C++

#include <hex/ui/imgui_imhex_extensions.h>
#include <imgui.h>
#define IMGUI_DEFINE_MATH_OPERATORS
#include <imgui_internal.h>
#undef IMGUI_DEFINE_MATH_OPERATORS
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
#include <string>
#include <imgui_impl_opengl3_loader.h>
#include <hex/api/imhex_api.hpp>
#include <fonts/codicons_font.h>
namespace ImGui {
Texture::Texture(const ImU8 *buffer, int size, int width, int height) {
unsigned char *imageData = stbi_load_from_memory(buffer, size, &this->m_width, &this->m_height, nullptr, 4);
if (imageData == nullptr) {
if (width * height * 4 > size)
return;
imageData = (unsigned char*) STBI_MALLOC(size);
std::memcpy(imageData, buffer, size);
this->m_width = width;
this->m_height = height;
}
if (imageData == nullptr)
return;
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
#if defined(GL_UNPACK_ROW_LENGTH)
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->m_width, this->m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
stbi_image_free(imageData);
this->m_textureId = reinterpret_cast<ImTextureID>(static_cast<intptr_t>(texture));
}
Texture::Texture(const char *path) {
unsigned char *imageData = stbi_load(path, &this->m_width, &this->m_height, nullptr, 4);
if (imageData == nullptr)
return;
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
#if defined(GL_UNPACK_ROW_LENGTH)
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->m_width, this->m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
stbi_image_free(imageData);
this->m_textureId = reinterpret_cast<ImTextureID>(static_cast<intptr_t>(texture));
}
Texture::Texture(unsigned int texture, int width, int height) : m_textureId(reinterpret_cast<ImTextureID>(static_cast<intptr_t>(texture))), m_width(width), m_height(height) {
}
Texture::Texture(Texture&& other) noexcept {
glDeleteTextures(1, reinterpret_cast<GLuint*>(&this->m_textureId));
this->m_textureId = other.m_textureId;
this->m_width = other.m_width;
this->m_height = other.m_height;
other.m_textureId = nullptr;
}
Texture& Texture::operator=(Texture&& other) noexcept {
glDeleteTextures(1, reinterpret_cast<GLuint*>(&this->m_textureId));
this->m_textureId = other.m_textureId;
this->m_width = other.m_width;
this->m_height = other.m_height;
other.m_textureId = nullptr;
return *this;
}
Texture::~Texture() {
if (this->m_textureId == nullptr)
return;
auto glTextureId = static_cast<GLuint>(reinterpret_cast<intptr_t>(this->m_textureId));
glDeleteTextures(1, &glTextureId);
}
int UpdateStringSizeCallback(ImGuiInputTextCallbackData *data) {
if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) {
auto &string = *static_cast<std::string *>(data->UserData);
string.resize(data->BufTextLen);
data->Buf = string.data();
}
return 0;
}
bool IconHyperlink(const char *icon, const char *label, const ImVec2 &size_arg, ImGuiButtonFlags flags) {
ImGuiWindow *window = GetCurrentWindow();
if (window->SkipItems)
return false;
ImGuiContext &g = *GImGui;
const ImGuiID id = window->GetID(label);
ImVec2 label_size = CalcTextSize(icon, nullptr, false);
label_size.x += CalcTextSize(" ", nullptr, false).x + CalcTextSize(label, nullptr, false).x;
ImVec2 pos = window->DC.CursorPos;
ImVec2 size = CalcItemSize(size_arg, label_size.x, label_size.y);
const ImRect bb(pos, pos + size);
if (!ItemAdd(bb, id))
return false;
if (g.LastItemData.InFlags & ImGuiItemFlags_ButtonRepeat)
flags |= ImGuiButtonFlags_Repeat;
bool hovered, held;
bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
// Render
const ImU32 col = hovered ? GetColorU32(ImGuiCol_ButtonHovered) : GetColorU32(ImGuiCol_ButtonActive);
PushStyleColor(ImGuiCol_Text, ImU32(col));
Text("%s %s", icon, label);
GetWindowDrawList()->AddLine(ImVec2(pos.x, pos.y + size.y), pos + size, ImU32(col));
PopStyleColor();
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
return pressed;
}
bool Hyperlink(const char *label, const ImVec2 &size_arg, ImGuiButtonFlags flags) {
ImGuiWindow *window = GetCurrentWindow();
if (window->SkipItems)
return false;
ImGuiContext &g = *GImGui;
const ImGuiID id = window->GetID(label);
const ImVec2 label_size = CalcTextSize(label, nullptr, true);
ImVec2 pos = window->DC.CursorPos;
ImVec2 size = CalcItemSize(size_arg, label_size.x, label_size.y);
const ImRect bb(pos, pos + size);
if (!ItemAdd(bb, id))
return false;
if (g.LastItemData.InFlags & ImGuiItemFlags_ButtonRepeat)
flags |= ImGuiButtonFlags_Repeat;
bool hovered, held;
bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
// Render
const ImU32 col = hovered ? GetColorU32(ImGuiCol_ButtonHovered) : GetColorU32(ImGuiCol_ButtonActive);
PushStyleColor(ImGuiCol_Text, ImU32(col));
TextEx(label, nullptr, ImGuiTextFlags_NoWidthForLargeClippedText); // Skip formatting
GetWindowDrawList()->AddLine(ImVec2(pos.x, pos.y + size.y), pos + size, ImU32(col));
PopStyleColor();
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
return pressed;
}
bool BulletHyperlink(const char *label, const ImVec2 &size_arg, ImGuiButtonFlags flags) {
ImGuiWindow *window = GetCurrentWindow();
if (window->SkipItems)
return false;
ImGuiContext &g = *GImGui;
const ImGuiStyle &style = g.Style;
const ImGuiID id = window->GetID(label);
const ImVec2 label_size = CalcTextSize(label, nullptr, true);
ImVec2 pos = window->DC.CursorPos;
ImVec2 size = CalcItemSize(size_arg, label_size.x, label_size.y) + ImVec2(g.FontSize + style.FramePadding.x * 2, 0.0f);
const ImRect bb(pos, pos + size);
ItemSize(size, 0);
if (!ItemAdd(bb, id))
return false;
if (g.LastItemData.InFlags & ImGuiItemFlags_ButtonRepeat)
flags |= ImGuiButtonFlags_Repeat;
bool hovered, held;
bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
// Render
const ImU32 col = hovered ? GetColorU32(ImGuiCol_ButtonHovered) : GetColorU32(ImGuiCol_ButtonActive);
PushStyleColor(ImGuiCol_Text, ImU32(col));
RenderBullet(window->DrawList, bb.Min + ImVec2(style.FramePadding.x, g.FontSize * 0.5f), col);
RenderText(bb.Min + ImVec2(g.FontSize * 0.5 + style.FramePadding.x, 0.0f), label, nullptr, false);
GetWindowDrawList()->AddLine(bb.Min + ImVec2(g.FontSize * 0.5 + style.FramePadding.x, size.y), pos + size - ImVec2(g.FontSize * 0.5 + style.FramePadding.x, 0), ImU32(col));
PopStyleColor();
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
return pressed;
}
bool DescriptionButton(const char *label, const char *description, const ImVec2 &size_arg, ImGuiButtonFlags flags) {
ImGuiWindow *window = GetCurrentWindow();
if (window->SkipItems)
return false;
ImGuiContext &g = *GImGui;
const ImGuiStyle &style = g.Style;
const ImGuiID id = window->GetID(label);
const ImVec2 text_size = CalcTextSize((std::string(label) + "\n " + std::string(description)).c_str(), nullptr, true);
const ImVec2 label_size = CalcTextSize(label, nullptr, true);
ImVec2 pos = window->DC.CursorPos;
if ((flags & ImGuiButtonFlags_AlignTextBaseLine) && style.FramePadding.y < window->DC.CurrLineTextBaseOffset) // Try to vertically align buttons that are smaller/have no padding so that text baseline matches (bit hacky, since it shouldn't be a flag)
pos.y += window->DC.CurrLineTextBaseOffset - style.FramePadding.y;
ImVec2 size = CalcItemSize(size_arg, text_size.x + style.FramePadding.x * 4.0f, text_size.y + style.FramePadding.y * 4.0f);
const ImRect bb(pos, pos + size);
ItemSize(size, style.FramePadding.y);
if (!ItemAdd(bb, id))
return false;
if (g.LastItemData.InFlags & ImGuiItemFlags_ButtonRepeat)
flags |= ImGuiButtonFlags_Repeat;
bool hovered, held;
bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0, 0.5));
// Render
const ImU32 col = GetCustomColorU32((held && hovered) ? ImGuiCustomCol_DescButtonActive : hovered ? ImGuiCustomCol_DescButtonHovered
: ImGuiCustomCol_DescButton);
RenderNavHighlight(bb, id);
RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
PushStyleColor(ImGuiCol_Text, GetColorU32(ImGuiCol_ButtonActive));
RenderTextWrapped(bb.Min + style.FramePadding * 2, label, nullptr, CalcWrapWidthForPos(window->DC.CursorPos, window->DC.TextWrapPos));
PopStyleColor();
PushStyleColor(ImGuiCol_Text, GetColorU32(ImGuiCol_Text));
RenderTextClipped(bb.Min + style.FramePadding * 2 + ImVec2(style.FramePadding.x * 2, label_size.y), bb.Max - style.FramePadding, description, nullptr, &text_size, style.ButtonTextAlign, &bb);
PopStyleColor();
ImGui::PopStyleVar();
// Automatically close popups
// if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup))
// CloseCurrentPopup();
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
return pressed;
}
void HelpHover(const char *text) {
const auto iconColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonActive);
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0, 0, 0, 0));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0, 0, 0, 0));
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, ImGui::GetStyle().FramePadding.y));
ImGui::PushStyleColor(ImGuiCol_Text, iconColor);
ImGui::Button(ICON_VS_INFO);
ImGui::PopStyleColor();
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
ImGui::SetNextWindowSizeConstraints(ImVec2(ImGui::GetTextLineHeight() * 25, 0), ImVec2(ImGui::GetTextLineHeight() * 25, FLT_MAX));
ImGui::BeginTooltip();
ImGui::TextFormattedWrapped("{}", text);
ImGui::EndTooltip();
}
ImGui::PopStyleVar();
ImGui::PopStyleColor(3);
}
void UnderlinedText(const char *label, ImColor color, const ImVec2 &size_arg) {
ImGuiWindow *window = GetCurrentWindow();
const ImVec2 label_size = CalcTextSize(label, nullptr, true);
ImVec2 pos = window->DC.CursorPos;
ImVec2 size = CalcItemSize(size_arg, label_size.x, label_size.y);
PushStyleColor(ImGuiCol_Text, ImU32(color));
TextEx(label, nullptr, ImGuiTextFlags_NoWidthForLargeClippedText); // Skip formatting
GetWindowDrawList()->AddLine(ImVec2(pos.x, pos.y + size.y), pos + size, ImU32(color));
PopStyleColor();
}
void TextSpinner(const char *label) {
ImGui::Text("[%c] %s", "|/-\\"[ImU32(ImGui::GetTime() * 20) % 4], label);
}
void Header(const char *label, bool firstEntry) {
if (!firstEntry)
ImGui::NewLine();
ImGui::TextUnformatted(label);
ImGui::Separator();
}
void HeaderColored(const char *label, ImColor color, bool firstEntry) {
if (!firstEntry)
ImGui::NewLine();
ImGui::TextFormattedColored(color, "{}", label);
ImGui::Separator();
}
void InfoTooltip(const char *text) {
static double lastMoveTime;
static ImGuiID lastHoveredID;
double currTime = ImGui::GetTime();
ImGuiID hoveredID = ImGui::GetHoveredID();
if (IsItemHovered() && (currTime - lastMoveTime) >= 0.5 && hoveredID == lastHoveredID) {
BeginTooltip();
TextUnformatted(text);
EndTooltip();
}
if (hoveredID != lastHoveredID) {
lastMoveTime = currTime;
}
lastHoveredID = hoveredID;
}
ImU32 GetCustomColorU32(ImGuiCustomCol idx, float alpha_mul) {
auto &customData = *static_cast<ImHexCustomData *>(GImGui->IO.UserData);
ImVec4 c = customData.Colors[idx];
c.w *= GImGui->Style.Alpha * alpha_mul;
return ColorConvertFloat4ToU32(c);
}
ImVec4 GetCustomColorVec4(ImGuiCustomCol idx, float alpha_mul) {
auto &customData = *static_cast<ImHexCustomData *>(GImGui->IO.UserData);
ImVec4 c = customData.Colors[idx];
c.w *= GImGui->Style.Alpha * alpha_mul;
return c;
}
void StyleCustomColorsDark() {
auto &colors = static_cast<ImHexCustomData *>(GImGui->IO.UserData)->Colors;
colors[ImGuiCustomCol_DescButton] = ImColor(20, 20, 20);
colors[ImGuiCustomCol_DescButtonHovered] = ImColor(40, 40, 40);
colors[ImGuiCustomCol_DescButtonActive] = ImColor(60, 60, 60);
colors[ImGuiCustomCol_ToolbarGray] = ImColor(230, 230, 230);
colors[ImGuiCustomCol_ToolbarRed] = ImColor(231, 76, 60);
colors[ImGuiCustomCol_ToolbarYellow] = ImColor(241, 196, 15);
colors[ImGuiCustomCol_ToolbarGreen] = ImColor(56, 139, 66);
colors[ImGuiCustomCol_ToolbarBlue] = ImColor(6, 83, 155);
colors[ImGuiCustomCol_ToolbarPurple] = ImColor(103, 42, 120);
colors[ImGuiCustomCol_ToolbarBrown] = ImColor(219, 179, 119);
colors[ImGuiCustomCol_Highlight] = ImColor(77, 198, 155);
colors[ImGuiCustomCol_IEEEToolSign] = ImColor(93, 93, 127);
colors[ImGuiCustomCol_IEEEToolExp] = ImColor(93, 127, 93);
colors[ImGuiCustomCol_IEEEToolMantissa] = ImColor(127, 93, 93);
}
void StyleCustomColorsLight() {
auto &colors = static_cast<ImHexCustomData *>(GImGui->IO.UserData)->Colors;
colors[ImGuiCustomCol_DescButton] = ImColor(230, 230, 230);
colors[ImGuiCustomCol_DescButtonHovered] = ImColor(210, 210, 210);
colors[ImGuiCustomCol_DescButtonActive] = ImColor(190, 190, 190);
colors[ImGuiCustomCol_ToolbarGray] = ImColor(25, 25, 25);
colors[ImGuiCustomCol_ToolbarRed] = ImColor(231, 76, 60);
colors[ImGuiCustomCol_ToolbarYellow] = ImColor(241, 196, 15);
colors[ImGuiCustomCol_ToolbarGreen] = ImColor(56, 139, 66);
colors[ImGuiCustomCol_ToolbarBlue] = ImColor(6, 83, 155);
colors[ImGuiCustomCol_ToolbarPurple] = ImColor(103, 42, 120);
colors[ImGuiCustomCol_ToolbarBrown] = ImColor(219, 179, 119);
colors[ImGuiCustomCol_Highlight] = ImColor(41, 151, 112);
colors[ImGuiCustomCol_IEEEToolSign] = ImColor(187, 187, 255);
colors[ImGuiCustomCol_IEEEToolExp] = ImColor(187, 255, 187);
colors[ImGuiCustomCol_IEEEToolMantissa] = ImColor(255, 187,187);
}
void StyleCustomColorsClassic() {
auto &colors = static_cast<ImHexCustomData *>(GImGui->IO.UserData)->Colors;
colors[ImGuiCustomCol_DescButton] = ImColor(40, 40, 80);
colors[ImGuiCustomCol_DescButtonHovered] = ImColor(60, 60, 100);
colors[ImGuiCustomCol_DescButtonActive] = ImColor(80, 80, 120);
colors[ImGuiCustomCol_ToolbarGray] = ImColor(230, 230, 230);
colors[ImGuiCustomCol_ToolbarRed] = ImColor(231, 76, 60);
colors[ImGuiCustomCol_ToolbarYellow] = ImColor(241, 196, 15);
colors[ImGuiCustomCol_ToolbarGreen] = ImColor(56, 139, 66);
colors[ImGuiCustomCol_ToolbarBlue] = ImColor(6, 83, 155);
colors[ImGuiCustomCol_ToolbarPurple] = ImColor(103, 42, 120);
colors[ImGuiCustomCol_ToolbarBrown] = ImColor(219, 179, 119);
colors[ImGuiCustomCol_Highlight] = ImColor(77, 198, 155);
colors[ImGuiCustomCol_IEEEToolSign] = ImColor(93, 93, 127);
colors[ImGuiCustomCol_IEEEToolExp] = ImColor(93, 127, 93);
colors[ImGuiCustomCol_IEEEToolMantissa] = ImColor(127, 93, 93);
}
void OpenPopupInWindow(const char *window_name, const char *popup_name) {
if (ImGui::Begin(window_name)) {
ImGui::OpenPopup(popup_name);
}
ImGui::End();
}
bool TitleBarButton(const char *label, ImVec2 size_arg) {
ImGuiWindow *window = GetCurrentWindow();
if (window->SkipItems)
return false;
ImGuiContext &g = *GImGui;
const ImGuiStyle &style = g.Style;
const ImGuiID id = window->GetID(label);
const ImVec2 label_size = CalcTextSize(label, nullptr, true);
ImVec2 pos = window->DC.CursorPos;
ImVec2 size = CalcItemSize(size_arg, label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f);
const ImRect bb(pos, pos + size);
ItemSize(size, style.FramePadding.y);
if (!ItemAdd(bb, id))
return false;
bool hovered, held;
bool pressed = ButtonBehavior(bb, id, &hovered, &held);
// Render
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered
: ImGuiCol_Button);
RenderNavHighlight(bb, id);
RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
RenderTextClipped(bb.Min + style.FramePadding * ImVec2(1, 2), bb.Max - style.FramePadding, label, nullptr, &label_size, style.ButtonTextAlign, &bb);
// Automatically close popups
// if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup))
// CloseCurrentPopup();
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
return pressed;
}
bool ToolBarButton(const char *symbol, ImVec4 color) {
ImGuiWindow *window = GetCurrentWindow();
if (window->SkipItems)
return false;
color.w = 1.0F;
ImGuiContext &g = *GImGui;
const ImGuiStyle &style = g.Style;
const ImGuiID id = window->GetID(symbol);
const ImVec2 label_size = CalcTextSize(symbol, nullptr, true);
ImVec2 pos = window->DC.CursorPos;
ImVec2 size = CalcItemSize(ImVec2(1, 1) * ImGui::GetCurrentWindow()->MenuBarHeight(), label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f);
const ImRect bb(pos, pos + size);
ItemSize(size, style.FramePadding.y);
if (!ItemAdd(bb, id))
return false;
bool hovered, held;
bool pressed = ButtonBehavior(bb, id, &hovered, &held);
PushStyleColor(ImGuiCol_Text, color);
// Render
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered
: ImGuiCol_MenuBarBg);
RenderNavHighlight(bb, id);
RenderFrame(bb.Min, bb.Max, col, false, style.FrameRounding);
RenderTextClipped(bb.Min + style.FramePadding * ImVec2(1, 2), bb.Max - style.FramePadding, symbol, nullptr, &label_size, style.ButtonTextAlign, &bb);
PopStyleColor();
// Automatically close popups
// if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup))
// CloseCurrentPopup();
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
return pressed;
}
bool IconButton(const char *symbol, ImVec4 color, ImVec2 size_arg) {
ImGuiWindow *window = GetCurrentWindow();
if (window->SkipItems)
return false;
color.w = 1.0F;
ImGuiContext &g = *GImGui;
const ImGuiStyle &style = g.Style;
const ImGuiID id = window->GetID(symbol);
const ImVec2 label_size = CalcTextSize(symbol, nullptr, true);
ImVec2 pos = window->DC.CursorPos;
ImVec2 size = CalcItemSize(size_arg, label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f);
const ImRect bb(pos, pos + size);
ItemSize(size, style.FramePadding.y);
if (!ItemAdd(bb, id))
return false;
bool hovered, held;
bool pressed = ButtonBehavior(bb, id, &hovered, &held);
PushStyleColor(ImGuiCol_Text, color);
// Render
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered
: ImGuiCol_Button);
RenderNavHighlight(bb, id);
RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
RenderTextClipped(bb.Min + style.FramePadding * ImVec2(1, 2), bb.Max - style.FramePadding, symbol, nullptr, &label_size, style.ButtonTextAlign, &bb);
PopStyleColor();
// Automatically close popups
// if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup))
// CloseCurrentPopup();
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
return pressed;
}
bool InputIntegerPrefix(const char *label, const char *prefix, void *value, ImGuiDataType type, const char *format, ImGuiInputTextFlags flags) {
auto window = ImGui::GetCurrentWindow();
const ImGuiID id = window->GetID(label);
const ImGuiStyle &style = GImGui->Style;
const ImVec2 label_size = CalcTextSize(label, nullptr, true);
const ImVec2 frame_size = CalcItemSize(ImVec2(0, 0), CalcTextSize(prefix).x, label_size.y + style.FramePadding.y * 2.0f);
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size);
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + frame_size.x);
char buf[64];
DataTypeFormatString(buf, IM_ARRAYSIZE(buf), type, value, format);
bool value_changed = false;
if (InputTextEx(label, nullptr, buf, IM_ARRAYSIZE(buf), ImVec2(CalcItemWidth() - frame_size.x, label_size.y + style.FramePadding.y * 2.0f), flags))
value_changed = DataTypeApplyFromText(buf, type, value, format);
if (value_changed)
MarkItemEdited(GImGui->LastItemData.ID);
RenderNavHighlight(frame_bb, id);
RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.6F);
RenderText(ImVec2(frame_bb.Min.x + style.FramePadding.x, frame_bb.Min.y + style.FramePadding.y), prefix);
ImGui::PopStyleVar();
return value_changed;
}
bool InputHexadecimal(const char *label, u32 *value, ImGuiInputTextFlags flags) {
return InputIntegerPrefix(label, "0x", value, ImGuiDataType_U32, "%lX", flags | ImGuiInputTextFlags_CharsHexadecimal);
}
bool InputHexadecimal(const char *label, u64 *value, ImGuiInputTextFlags flags) {
return InputIntegerPrefix(label, "0x", value, ImGuiDataType_U64, "%llX", flags | ImGuiInputTextFlags_CharsHexadecimal);
}
void SmallProgressBar(float fraction, float yOffset) {
ImGuiWindow *window = GetCurrentWindow();
if (window->SkipItems)
return;
ImGuiContext &g = *GImGui;
const ImGuiStyle &style = g.Style;
ImVec2 pos = window->DC.CursorPos + ImVec2(0, yOffset);
ImVec2 size = CalcItemSize(ImVec2(100, 5) * hex::ImHexApi::System::getGlobalScale(), 100, g.FontSize + style.FramePadding.y * 2.0f);
ImRect bb(pos, pos + size);
ItemSize(size, 0);
if (!ItemAdd(bb, 0))
return;
// Render
fraction = ImSaturate(fraction);
RenderFrame(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
bb.Expand(ImVec2(-style.FrameBorderSize, -style.FrameBorderSize));
RenderRectFilledRangeH(window->DrawList, bb, GetColorU32(ImGuiCol_PlotHistogram), 0.0f, fraction, style.FrameRounding);
}
bool InputText(const char *label, std::string &buffer, ImGuiInputTextFlags flags) {
return ImGui::InputText(label, buffer.data(), buffer.size() + 1, ImGuiInputTextFlags_CallbackResize | flags, ImGui::UpdateStringSizeCallback, &buffer);
}
bool InputTextIcon(const char *label, const char *icon, std::string &buffer, ImGuiInputTextFlags flags) {
auto window = ImGui::GetCurrentWindow();
const ImGuiID id = window->GetID(label);
const ImGuiStyle &style = GImGui->Style;
const ImVec2 label_size = CalcTextSize(label, nullptr, true);
const ImVec2 icon_frame_size = CalcTextSize(icon) + style.FramePadding * 2.0f;
const ImVec2 frame_size = CalcItemSize(ImVec2(0, 0), icon_frame_size.x, label_size.y + style.FramePadding.y * 2.0f);
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size);
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + frame_size.x);
bool value_changed = ImGui::InputTextEx(label, nullptr, buffer.data(), buffer.size() + 1, ImVec2(CalcItemWidth() - frame_size.x, label_size.y + style.FramePadding.y * 2.0f), ImGuiInputTextFlags_CallbackResize | flags, ImGui::UpdateStringSizeCallback, &buffer);
if (value_changed)
MarkItemEdited(GImGui->LastItemData.ID);
RenderNavHighlight(frame_bb, id);
RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
RenderFrame(frame_bb.Min, frame_bb.Min + icon_frame_size, GetColorU32(ImGuiCol_TableBorderStrong), true, style.FrameRounding);
RenderText(ImVec2(frame_bb.Min.x + style.FramePadding.x, frame_bb.Min.y + style.FramePadding.y * 2), icon);
return value_changed;
}
bool InputTextWithHint(const char *label, const char *hint, std::string &buffer, ImGuiInputTextFlags flags) {
return ImGui::InputTextWithHint(label, hint, buffer.data(), buffer.size() + 1, ImGuiInputTextFlags_CallbackResize | flags, ImGui::UpdateStringSizeCallback, &buffer);
}
bool InputText(const char *label, std::u8string &buffer, ImGuiInputTextFlags flags) {
return ImGui::InputText(label, reinterpret_cast<char *>(buffer.data()), buffer.size() + 1, ImGuiInputTextFlags_CallbackResize | flags, ImGui::UpdateStringSizeCallback, &buffer);
}
bool InputTextMultiline(const char *label, std::string &buffer, const ImVec2 &size, ImGuiInputTextFlags flags) {
return ImGui::InputTextMultiline(label, buffer.data(), buffer.size() + 1, size, ImGuiInputTextFlags_CallbackResize | flags, ImGui::UpdateStringSizeCallback, &buffer);
}
bool InputScalarCallback(const char* label, ImGuiDataType data_type, void* p_data, const char* format, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) {
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return false;
ImGuiContext& g = *GImGui;
if (format == nullptr)
format = DataTypeGetInfo(data_type)->PrintFmt;
char buf[64];
DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, p_data, format);
bool value_changed = false;
if ((flags & (ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsScientific)) == 0)
flags |= ImGuiInputTextFlags_CharsDecimal;
flags |= ImGuiInputTextFlags_AutoSelectAll;
flags |= ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselves by comparing the actual data rather than the string.
if (InputText(label, buf, IM_ARRAYSIZE(buf), flags, callback, user_data))
value_changed = DataTypeApplyFromText(buf, data_type, p_data, format);
if (value_changed)
MarkItemEdited(g.LastItemData.ID);
return value_changed;
}
void HideTooltip() {
char window_name[16];
ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", GImGui->TooltipOverrideCount);
if (ImGuiWindow* window = FindWindowByName(window_name); window != nullptr) {
if (window->Active)
window->Hidden = true;
}
}
bool BitCheckbox(const char* label, bool* v) {
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return false;
ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style;
const ImGuiID id = window->GetID(label);
const ImVec2 label_size = CalcTextSize(label, nullptr, true);
const ImVec2 size = ImVec2(CalcTextSize("0").x + style.FramePadding.x * 2, GetFrameHeight());
const ImVec2 pos = window->DC.CursorPos;
const ImRect total_bb(pos, pos + size);
ItemSize(total_bb, style.FramePadding.y);
if (!ItemAdd(total_bb, id))
{
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));
return false;
}
bool hovered, held;
bool pressed = ButtonBehavior(total_bb, id, &hovered, &held);
if (pressed)
{
*v = !(*v);
MarkItemEdited(id);
}
const ImRect check_bb(pos, pos + size);
RenderNavHighlight(total_bb, id);
RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
RenderText(check_bb.Min + style.FramePadding, *v ? "1" : "0");
ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y);
if (label_size.x > 0.0f)
RenderText(label_pos, label);
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));
return pressed;
}
bool DimmedButton(const char* label){
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::GetCustomColorU32(ImGuiCustomCol_DescButtonHovered));
ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetCustomColorU32(ImGuiCustomCol_DescButton));
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_ButtonActive));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImGui::GetCustomColorU32(ImGuiCustomCol_DescButtonActive));
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1);
bool res = ImGui::Button(label);
ImGui::PopStyleColor(4);
ImGui::PopStyleVar(1);
return res;
}
bool DimmedIconButton(const char *symbol, ImVec4 color, ImVec2 size_arg){
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::GetCustomColorU32(ImGuiCustomCol_DescButtonHovered));
ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetCustomColorU32(ImGuiCustomCol_DescButton));
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_ButtonActive));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImGui::GetCustomColorU32(ImGuiCustomCol_DescButtonActive));
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1);
bool res = IconButton(symbol, color, size_arg);
ImGui::PopStyleColor(4);
ImGui::PopStyleVar(1);
return res;
}
}