3e4c4430d5
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.
347 lines
24 KiB
C++
347 lines
24 KiB
C++
#include <hex/api/theme_manager.hpp>
|
|
|
|
#include <imgui.h>
|
|
#include <imgui_internal.h>
|
|
#include <implot.h>
|
|
#include <hex/ui/imgui_imhex_extensions.h>
|
|
#include <imnodes.h>
|
|
#include <TextEditor.h>
|
|
#include <romfs/romfs.hpp>
|
|
|
|
#include <hex/helpers/utils.hpp>
|
|
#include <hex/helpers/fs.hpp>
|
|
|
|
#include <hex/api/event.hpp>
|
|
|
|
#include <wolv/io/file.hpp>
|
|
|
|
namespace hex::plugin::builtin {
|
|
|
|
void registerThemeHandlers() {
|
|
EventManager::subscribe<RequestInitThemeHandlers>([]() {
|
|
{
|
|
const static ThemeManager::ColorMap ImGuiColorMap = {
|
|
{ "text", ImGuiCol_Text },
|
|
{ "text-disabled", ImGuiCol_TextDisabled },
|
|
{ "window-background", ImGuiCol_WindowBg },
|
|
{ "child-background", ImGuiCol_ChildBg },
|
|
{ "popup-background", ImGuiCol_PopupBg },
|
|
{ "border", ImGuiCol_Border },
|
|
{ "border-shadow", ImGuiCol_BorderShadow },
|
|
{ "frame-background", ImGuiCol_FrameBg },
|
|
{ "frame-background-hovered", ImGuiCol_FrameBgHovered },
|
|
{ "frame-background-active", ImGuiCol_FrameBgActive },
|
|
{ "title-background", ImGuiCol_TitleBg },
|
|
{ "title-background-active", ImGuiCol_TitleBgActive },
|
|
{ "title-background-collapse", ImGuiCol_TitleBgCollapsed },
|
|
{ "menu-bar-background", ImGuiCol_MenuBarBg },
|
|
{ "scrollbar-background", ImGuiCol_ScrollbarBg },
|
|
{ "scrollbar-grab", ImGuiCol_ScrollbarGrab },
|
|
{ "scrollbar-grab-hovered", ImGuiCol_ScrollbarGrabHovered },
|
|
{ "scrollbar-grab-active", ImGuiCol_ScrollbarGrabActive },
|
|
{ "check-mark", ImGuiCol_CheckMark },
|
|
{ "slider-grab", ImGuiCol_SliderGrab },
|
|
{ "slider-grab-active", ImGuiCol_SliderGrabActive },
|
|
{ "button", ImGuiCol_Button },
|
|
{ "button-hovered", ImGuiCol_ButtonHovered },
|
|
{ "button-active", ImGuiCol_ButtonActive },
|
|
{ "header", ImGuiCol_Header },
|
|
{ "header-hovered", ImGuiCol_HeaderHovered },
|
|
{ "header-active", ImGuiCol_HeaderActive },
|
|
{ "separator", ImGuiCol_Separator },
|
|
{ "separator-hovered", ImGuiCol_SeparatorHovered },
|
|
{ "separator-active", ImGuiCol_SeparatorActive },
|
|
{ "resize-grip", ImGuiCol_ResizeGrip },
|
|
{ "resize-grip-hovered", ImGuiCol_ResizeGripHovered },
|
|
{ "resize-grip-active", ImGuiCol_ResizeGripActive },
|
|
{ "tab", ImGuiCol_Tab },
|
|
{ "tab-hovered", ImGuiCol_TabHovered },
|
|
{ "tab-active", ImGuiCol_TabActive },
|
|
{ "tab-unfocused", ImGuiCol_TabUnfocused },
|
|
{ "tab-unfocused-active", ImGuiCol_TabUnfocusedActive },
|
|
{ "docking-preview", ImGuiCol_DockingPreview },
|
|
{ "docking-empty-background", ImGuiCol_DockingEmptyBg },
|
|
{ "plot-lines", ImGuiCol_PlotLines },
|
|
{ "plot-lines-hovered", ImGuiCol_PlotLinesHovered },
|
|
{ "plot-histogram", ImGuiCol_PlotHistogram },
|
|
{ "plot-histogram-hovered", ImGuiCol_PlotHistogramHovered },
|
|
{ "table-header-background", ImGuiCol_TableHeaderBg },
|
|
{ "table-border-strong", ImGuiCol_TableBorderStrong },
|
|
{ "table-border-light", ImGuiCol_TableBorderLight },
|
|
{ "table-row-background", ImGuiCol_TableRowBg },
|
|
{ "table-row-background-alt", ImGuiCol_TableRowBgAlt },
|
|
{ "text-selected-background", ImGuiCol_TextSelectedBg },
|
|
{ "drag-drop-target", ImGuiCol_DragDropTarget },
|
|
{ "nav-highlight", ImGuiCol_NavHighlight },
|
|
{ "nav-windowing-highlight", ImGuiCol_NavWindowingHighlight },
|
|
{ "nav-windowing-background", ImGuiCol_NavWindowingDimBg },
|
|
{ "modal-window-dim-background", ImGuiCol_ModalWindowDimBg }
|
|
};
|
|
|
|
ThemeManager::addThemeHandler("imgui", ImGuiColorMap,
|
|
[](u32 colorId) -> ImColor {
|
|
return ImGui::GetStyle().Colors[colorId];
|
|
},
|
|
[](u32 colorId, ImColor color) {
|
|
ImGui::GetStyle().Colors[colorId] = color;
|
|
}
|
|
);
|
|
}
|
|
|
|
{
|
|
const static ThemeManager::ColorMap ImPlotColorMap = {
|
|
{ "line", ImPlotCol_Line },
|
|
{ "fill", ImPlotCol_Fill },
|
|
{ "marker-outline", ImPlotCol_MarkerOutline },
|
|
{ "marker-fill", ImPlotCol_MarkerFill },
|
|
{ "error-bar", ImPlotCol_ErrorBar },
|
|
{ "frame-bg", ImPlotCol_FrameBg },
|
|
{ "plot-bg", ImPlotCol_PlotBg },
|
|
{ "plot-border", ImPlotCol_PlotBorder },
|
|
{ "legend-bg", ImPlotCol_LegendBg },
|
|
{ "legend-border", ImPlotCol_LegendBorder },
|
|
{ "legend-text", ImPlotCol_LegendText },
|
|
{ "title-text", ImPlotCol_TitleText },
|
|
{ "inlay-text", ImPlotCol_InlayText },
|
|
{ "axis-text", ImPlotCol_AxisText },
|
|
{ "axis-grid", ImPlotCol_AxisGrid },
|
|
{ "axis-tick", ImPlotCol_AxisTick },
|
|
{ "axis-bg", ImPlotCol_AxisBg },
|
|
{ "axis-bg-hovered", ImPlotCol_AxisBgHovered },
|
|
{ "axis-bg-active", ImPlotCol_AxisBgActive },
|
|
{ "selection", ImPlotCol_Selection },
|
|
{ "crosshairs", ImPlotCol_Crosshairs }
|
|
};
|
|
|
|
ThemeManager::addThemeHandler("implot", ImPlotColorMap,
|
|
[](u32 colorId) -> ImColor {
|
|
return ImPlot::GetStyle().Colors[colorId];
|
|
},
|
|
[](u32 colorId, ImColor color) {
|
|
ImPlot::GetStyle().Colors[colorId] = color;
|
|
}
|
|
);
|
|
}
|
|
|
|
{
|
|
const static ThemeManager::ColorMap ImNodesColorMap = {
|
|
{ "node-background", ImNodesCol_NodeBackground },
|
|
{ "node-background-hovered", ImNodesCol_NodeBackgroundHovered },
|
|
{ "node-background-selected", ImNodesCol_NodeBackgroundSelected },
|
|
{ "node-outline", ImNodesCol_NodeOutline },
|
|
{ "title-bar", ImNodesCol_TitleBar },
|
|
{ "title-bar-hovered", ImNodesCol_TitleBarHovered },
|
|
{ "title-bar-selected", ImNodesCol_TitleBarSelected },
|
|
{ "link", ImNodesCol_Link },
|
|
{ "link-hovered", ImNodesCol_LinkHovered },
|
|
{ "link-selected", ImNodesCol_LinkSelected },
|
|
{ "pin", ImNodesCol_Pin },
|
|
{ "pin-hovered", ImNodesCol_PinHovered },
|
|
{ "box-selector", ImNodesCol_BoxSelector },
|
|
{ "box-selector-outline", ImNodesCol_BoxSelectorOutline },
|
|
{ "grid-background", ImNodesCol_GridBackground },
|
|
{ "grid-line", ImNodesCol_GridLine },
|
|
{ "grid-line-primary", ImNodesCol_GridLinePrimary },
|
|
{ "mini-map-background", ImNodesCol_MiniMapBackground },
|
|
{ "mini-map-background-hovered", ImNodesCol_MiniMapBackgroundHovered },
|
|
{ "mini-map-outline", ImNodesCol_MiniMapOutline },
|
|
{ "mini-map-outline-hovered", ImNodesCol_MiniMapOutlineHovered },
|
|
{ "mini-map-node-background", ImNodesCol_MiniMapNodeBackground },
|
|
{ "mini-map-node-background-hovered", ImNodesCol_MiniMapNodeBackgroundHovered },
|
|
{ "mini-map-node-background-selected", ImNodesCol_MiniMapNodeBackgroundSelected },
|
|
{ "mini-map-node-outline", ImNodesCol_MiniMapNodeOutline },
|
|
{ "mini-map-link", ImNodesCol_MiniMapLink },
|
|
{ "mini-map-link-selected", ImNodesCol_MiniMapLinkSelected },
|
|
{ "mini-map-canvas", ImNodesCol_MiniMapCanvas },
|
|
{ "mini-map-canvas-outline", ImNodesCol_MiniMapCanvasOutline },
|
|
};
|
|
|
|
ThemeManager::addThemeHandler("imnodes", ImNodesColorMap,
|
|
[](u32 colorId) -> ImColor {
|
|
return ImNodes::GetStyle().Colors[colorId];
|
|
},
|
|
[](u32 colorId, ImColor color) {
|
|
ImNodes::GetStyle().Colors[colorId] = color;
|
|
}
|
|
);
|
|
}
|
|
|
|
{
|
|
const static ThemeManager::ColorMap ImHexColorMap = {
|
|
{ "desc-button", ImGuiCustomCol_DescButton },
|
|
{ "desc-button-hovered", ImGuiCustomCol_DescButtonHovered },
|
|
{ "desc-button-active", ImGuiCustomCol_DescButtonActive },
|
|
{ "toolbar-gray", ImGuiCustomCol_ToolbarGray },
|
|
{ "toolbar-red", ImGuiCustomCol_ToolbarRed },
|
|
{ "toolbar-yellow", ImGuiCustomCol_ToolbarYellow },
|
|
{ "toolbar-green", ImGuiCustomCol_ToolbarGreen },
|
|
{ "toolbar-blue", ImGuiCustomCol_ToolbarBlue },
|
|
{ "toolbar-purple", ImGuiCustomCol_ToolbarPurple },
|
|
{ "toolbar-brown", ImGuiCustomCol_ToolbarBrown },
|
|
{ "highlight", ImGuiCustomCol_Highlight },
|
|
{ "IEEE-tool-sign", ImGuiCustomCol_IEEEToolSign },
|
|
{ "IEEE-tool-exp", ImGuiCustomCol_IEEEToolExp },
|
|
{ "IEEE-tool-mantissa", ImGuiCustomCol_IEEEToolMantissa }
|
|
|
|
};
|
|
|
|
ThemeManager::addThemeHandler("imhex", ImHexColorMap,
|
|
[](u32 colorId) -> ImColor {
|
|
return static_cast<ImGui::ImHexCustomData *>(GImGui->IO.UserData)->Colors[colorId];
|
|
|
|
},
|
|
[](u32 colorId, ImColor color) {
|
|
static_cast<ImGui::ImHexCustomData *>(GImGui->IO.UserData)->Colors[colorId] = color;
|
|
}
|
|
);
|
|
}
|
|
|
|
{
|
|
const static ThemeManager::ColorMap TextEditorColorMap = {
|
|
{ "default", u32(TextEditor::PaletteIndex::Default) },
|
|
{ "keyword", u32(TextEditor::PaletteIndex::Keyword) },
|
|
{ "number", u32(TextEditor::PaletteIndex::Number) },
|
|
{ "string", u32(TextEditor::PaletteIndex::String) },
|
|
{ "char-literal", u32(TextEditor::PaletteIndex::CharLiteral) },
|
|
{ "punctuation", u32(TextEditor::PaletteIndex::Punctuation) },
|
|
{ "preprocessor", u32(TextEditor::PaletteIndex::Preprocessor) },
|
|
{ "identifier", u32(TextEditor::PaletteIndex::Identifier) },
|
|
{ "known-identifier", u32(TextEditor::PaletteIndex::KnownIdentifier) },
|
|
{ "preproc-identifier", u32(TextEditor::PaletteIndex::PreprocIdentifier) },
|
|
{ "comment", u32(TextEditor::PaletteIndex::Comment) },
|
|
{ "multi-line-comment", u32(TextEditor::PaletteIndex::MultiLineComment) },
|
|
{ "background", u32(TextEditor::PaletteIndex::Background) },
|
|
{ "cursor", u32(TextEditor::PaletteIndex::Cursor) },
|
|
{ "selection", u32(TextEditor::PaletteIndex::Selection) },
|
|
{ "error-marker", u32(TextEditor::PaletteIndex::ErrorMarker) },
|
|
{ "breakpoint", u32(TextEditor::PaletteIndex::Breakpoint) },
|
|
{ "line-number", u32(TextEditor::PaletteIndex::LineNumber) },
|
|
{ "current-line-fill", u32(TextEditor::PaletteIndex::CurrentLineFill) },
|
|
{ "current-line-fill-inactive", u32(TextEditor::PaletteIndex::CurrentLineFillInactive) },
|
|
{ "current-line-edge", u32(TextEditor::PaletteIndex::CurrentLineEdge) }
|
|
};
|
|
|
|
ThemeManager::addThemeHandler("text-editor", TextEditorColorMap,
|
|
[](u32 colorId) -> ImColor {
|
|
return TextEditor::GetPalette()[colorId];
|
|
},
|
|
[](u32 colorId, ImColor color) {
|
|
auto palette = TextEditor::GetPalette();
|
|
palette[colorId] = color;
|
|
TextEditor::SetPalette(palette);
|
|
}
|
|
);
|
|
}
|
|
});
|
|
}
|
|
|
|
void registerStyleHandlers() {
|
|
EventManager::subscribe<RequestInitThemeHandlers>([]() {
|
|
{
|
|
auto &style = ImGui::GetStyle();
|
|
const static ThemeManager::StyleMap ImGuiStyleMap = {
|
|
{ "alpha", { &style.Alpha, 0.001F, 1.0F, false } },
|
|
{ "disabled-alpha", { &style.DisabledAlpha, 0.0F, 1.0F, false } },
|
|
{ "window-padding", { &style.WindowPadding, 0.0F, 20.0F, true } },
|
|
{ "window-rounding", { &style.WindowRounding, 0.0F, 12.0F, true } },
|
|
{ "window-border-size", { &style.WindowBorderSize, 0.0F, 1.0F, true } },
|
|
{ "window-min-size", { &style.WindowMinSize, 0.0F, 1000.0F, true } },
|
|
{ "window-title-align", { &style.WindowTitleAlign, 0.0F, 1.0F , false } },
|
|
{ "child-rounding", { &style.ChildRounding, 0.0F, 12.0F, true } },
|
|
{ "child-border-size", { &style.ChildBorderSize, 0.0F, 1.0F , true } },
|
|
{ "popup-rounding", { &style.PopupRounding, 0.0F, 12.0F, true } },
|
|
{ "popup-border-size", { &style.PopupBorderSize, 0.0F, 1.0F, true } },
|
|
{ "frame-padding", { &style.FramePadding, 0.0F, 20.0F, true } },
|
|
{ "frame-rounding", { &style.FrameRounding, 0.0F, 12.0F, true } },
|
|
{ "frame-border-size", { &style.FrameBorderSize, 0.0F, 1.0F, true } },
|
|
{ "item-spacing", { &style.ItemSpacing, 0.0F, 20.0F, true } },
|
|
{ "item-inner-spacing", { &style.ItemInnerSpacing, 0.0F, 20.0F, true } },
|
|
{ "indent-spacing", { &style.IndentSpacing, 0.0F, 30.0F, true } },
|
|
{ "cell-padding", { &style.CellPadding, 0.0F, 20.0F, true } },
|
|
{ "scrollbar-size", { &style.ScrollbarSize, 0.0F, 20.0F, true } },
|
|
{ "scrollbar-rounding", { &style.ScrollbarRounding, 0.0F, 12.0F, true } },
|
|
{ "grab-min-size", { &style.GrabMinSize, 0.0F, 20.0F, true } },
|
|
{ "grab-rounding", { &style.GrabRounding, 0.0F, 12.0F, true } },
|
|
{ "tab-rounding", { &style.TabRounding, 0.0F, 12.0F, true } },
|
|
{ "button-text-align", { &style.ButtonTextAlign, 0.0F, 1.0F, false } },
|
|
{ "selectable-text-align", { &style.SelectableTextAlign, 0.0F, 1.0F, false } },
|
|
};
|
|
|
|
ThemeManager::addStyleHandler("imgui", ImGuiStyleMap);
|
|
}
|
|
|
|
{
|
|
auto &style = ImPlot::GetStyle();
|
|
const static ThemeManager::StyleMap ImPlotStyleMap = {
|
|
{ "line-weight", { &style.LineWeight, 0.0F, 5.0F, true } },
|
|
{ "marker-size", { &style.MarkerSize, 2.0F, 10.0F, true } },
|
|
{ "marker-weight", { &style.MarkerWeight, 0.0F, 5.0F, true } },
|
|
{ "fill-alpha", { &style.FillAlpha, 0.0F, 1.0F, false } },
|
|
{ "error-bar-size", { &style.ErrorBarSize, 0.0F, 10.0F, true } },
|
|
{ "error-bar-weight", { &style.ErrorBarWeight, 0.0F, 5.0F, true } },
|
|
{ "digital-bit-height", { &style.DigitalBitHeight, 0.0F, 20.0F, true } },
|
|
{ "digital-bit-gap", { &style.DigitalBitGap, 0.0F, 20.0F, true } },
|
|
{ "plot-border-size", { &style.PlotBorderSize, 0.0F, 2.0F, true } },
|
|
{ "minor-alpha", { &style.MinorAlpha, 0.0F, 1.0F, false } },
|
|
{ "major-tick-len", { &style.MajorTickLen, 0.0F, 20.0F, true } },
|
|
{ "minor-tick-len", { &style.MinorTickLen, 0.0F, 20.0F, true } },
|
|
{ "major-tick-size", { &style.MajorTickSize, 0.0F, 2.0F, true } },
|
|
{ "minor-tick-size", { &style.MinorTickSize, 0.0F, 2.0F, true } },
|
|
{ "major-grid-size", { &style.MajorGridSize, 0.0F, 2.0F, true } },
|
|
{ "minor-grid-size", { &style.MinorGridSize, 0.0F, 2.0F, true } },
|
|
{ "plot-padding", { &style.PlotPadding, 0.0F, 20.0F, true } },
|
|
{ "label-padding", { &style.LabelPadding, 0.0F, 20.0F, true } },
|
|
{ "legend-padding", { &style.LegendPadding, 0.0F, 20.0F, true } },
|
|
{ "legend-inner-padding", { &style.LegendInnerPadding, 0.0F, 10.0F, true } },
|
|
{ "legend-spacing", { &style.LegendSpacing, 0.0F, 5.0F, true } },
|
|
{ "mouse-pos-padding", { &style.MousePosPadding, 0.0F, 20.0F, true } },
|
|
{ "annotation-padding", { &style.AnnotationPadding, 0.0F, 5.0F, true } },
|
|
{ "fit-padding", { &style.FitPadding, 0.0F, 0.2F, true } },
|
|
{ "plot-default-size", { &style.PlotDefaultSize, 0.0F, 1000.0F, true } },
|
|
{ "plot-min-size", { &style.PlotMinSize, 0.0F, 300.0F, true } },
|
|
};
|
|
|
|
ThemeManager::addStyleHandler("implot", ImPlotStyleMap);
|
|
}
|
|
|
|
{
|
|
auto &style = ImNodes::GetStyle();
|
|
const static ThemeManager::StyleMap ImNodesStyleMap = {
|
|
{ "grid-spacing", { &style.GridSpacing, 0.0F, 100.0F, true } },
|
|
{ "node-corner-rounding", { &style.NodeCornerRounding, 0.0F, 12.0F, true } },
|
|
{ "node-padding", { &style.NodePadding, 0.0F, 20.0F, true } },
|
|
{ "node-border-thickness", { &style.NodeBorderThickness, 0.0F, 1.0F, true } },
|
|
{ "link-thickness", { &style.LinkThickness, 0.0F, 10.0F, true } },
|
|
{ "link-line-segments-per-length", { &style.LinkLineSegmentsPerLength, 0.0F, 2.0F, true } },
|
|
{ "link-hover-distance", { &style.LinkHoverDistance, 0.0F, 20.0F, true } },
|
|
{ "pin-circle-radius", { &style.PinCircleRadius, 0.0F, 20.0F, true } },
|
|
{ "pin-quad-side-length", { &style.PinQuadSideLength, 0.0F, 20.0F, true } },
|
|
{ "pin-triangle-side-length", { &style.PinTriangleSideLength, 0.0F, 20.0F, true } },
|
|
{ "pin-line-thickness", { &style.PinLineThickness, 0.0F, 5.0F, true } },
|
|
{ "pin-hover-radius", { &style.PinHoverRadius, 0.0F, 20.0F, true } },
|
|
{ "pin-offset", { &style.PinOffset, -10.0F, 10.0F, true } },
|
|
{ "mini-map-padding", { &style.MiniMapPadding, 0.0F, 20.0F, true } },
|
|
{ "mini-map-offset", { &style.MiniMapOffset, -10.0F, 10.0F, true } },
|
|
};
|
|
|
|
ThemeManager::addStyleHandler("imnodes", ImNodesStyleMap);
|
|
}
|
|
});
|
|
}
|
|
|
|
void registerThemes() {
|
|
// Load built-in themes
|
|
for (const auto &theme : romfs::list("themes")) {
|
|
ThemeManager::addTheme(std::string(romfs::get(theme).string()));
|
|
}
|
|
|
|
// Load user themes
|
|
for (const auto &themeFolder : fs::getDefaultPaths(fs::ImHexPath::Themes)) {
|
|
for (const auto &theme : std::fs::directory_iterator(themeFolder)) {
|
|
if (theme.is_regular_file())
|
|
ThemeManager::addTheme(wolv::io::File(theme.path(), wolv::io::File::Mode::Read).readString());
|
|
}
|
|
}
|
|
}
|
|
|
|
} |