feat: Added Minimap to Hex Editor
This commit is contained in:
parent
17f769c40d
commit
069544eb93
@ -985,11 +985,19 @@ namespace hex {
|
|||||||
u16 m_maxCharsPerCell;
|
u16 m_maxCharsPerCell;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MiniMapVisualizer {
|
||||||
|
using Callback = std::function<ImColor(const std::vector<u8>&)>;
|
||||||
|
|
||||||
|
UnlocalizedString unlocalizedName;
|
||||||
|
Callback callback;
|
||||||
|
};
|
||||||
|
|
||||||
namespace impl {
|
namespace impl {
|
||||||
|
|
||||||
void addDataVisualizer(std::shared_ptr<DataVisualizer> &&visualizer);
|
void addDataVisualizer(std::shared_ptr<DataVisualizer> &&visualizer);
|
||||||
|
|
||||||
std::vector<std::shared_ptr<DataVisualizer>> &getVisualizers();
|
std::vector<std::shared_ptr<DataVisualizer>> &getVisualizers();
|
||||||
|
std::vector<std::shared_ptr<MiniMapVisualizer>> &getMiniMapVisualizers();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1010,6 +1018,13 @@ namespace hex {
|
|||||||
*/
|
*/
|
||||||
std::shared_ptr<DataVisualizer> getVisualizerByName(const UnlocalizedString &unlocalizedName);
|
std::shared_ptr<DataVisualizer> getVisualizerByName(const UnlocalizedString &unlocalizedName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adds a new minimap visualizer
|
||||||
|
* @param unlocalizedName Unlocalized name of the minimap visualizer
|
||||||
|
* @param callback The callback that will be called to get the color of a line
|
||||||
|
*/
|
||||||
|
void addMiniMapVisualizer(UnlocalizedString unlocalizedName, MiniMapVisualizer::Callback callback);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Diffing Registry. Allows adding new diffing algorithms */
|
/* Diffing Registry. Allows adding new diffing algorithms */
|
||||||
|
@ -1001,6 +1001,12 @@ namespace hex {
|
|||||||
return visualizers;
|
return visualizers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<MiniMapVisualizer>> &getMiniMapVisualizers() {
|
||||||
|
static std::vector<std::shared_ptr<MiniMapVisualizer>> visualizers;
|
||||||
|
|
||||||
|
return visualizers;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<DataVisualizer> getVisualizerByName(const UnlocalizedString &unlocalizedName) {
|
std::shared_ptr<DataVisualizer> getVisualizerByName(const UnlocalizedString &unlocalizedName) {
|
||||||
@ -1012,6 +1018,10 @@ namespace hex {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addMiniMapVisualizer(UnlocalizedString unlocalizedName, MiniMapVisualizer::Callback callback) {
|
||||||
|
impl::getMiniMapVisualizers().emplace_back(std::make_shared<MiniMapVisualizer>(std::move(unlocalizedName), std::move(callback)));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ContentRegistry::Diffing {
|
namespace ContentRegistry::Diffing {
|
||||||
|
@ -45,6 +45,7 @@ add_imhex_plugin(
|
|||||||
source/content/workspaces.cpp
|
source/content/workspaces.cpp
|
||||||
source/content/pl_visualizers.cpp
|
source/content/pl_visualizers.cpp
|
||||||
source/content/out_of_box_experience.cpp
|
source/content/out_of_box_experience.cpp
|
||||||
|
source/content/minimap_visualizers.cpp
|
||||||
|
|
||||||
source/content/data_processor_nodes/basic_nodes.cpp
|
source/content/data_processor_nodes/basic_nodes.cpp
|
||||||
source/content/data_processor_nodes/control_nodes.cpp
|
source/content/data_processor_nodes/control_nodes.cpp
|
||||||
|
@ -171,6 +171,8 @@
|
|||||||
"hex.builtin.menu.view.debug": "Show Debugging View",
|
"hex.builtin.menu.view.debug": "Show Debugging View",
|
||||||
"hex.builtin.menu.view.demo": "Show ImGui Demo",
|
"hex.builtin.menu.view.demo": "Show ImGui Demo",
|
||||||
"hex.builtin.menu.view.fps": "Display FPS",
|
"hex.builtin.menu.view.fps": "Display FPS",
|
||||||
|
"hex.builtin.minimap_visualizer.entropy": "Local Entropy",
|
||||||
|
"hex.builtin.minimap_visualizer.zeros": "Zeros Count",
|
||||||
"hex.builtin.nodes.arithmetic": "Arithmetic",
|
"hex.builtin.nodes.arithmetic": "Arithmetic",
|
||||||
"hex.builtin.nodes.arithmetic.add": "Addition",
|
"hex.builtin.nodes.arithmetic.add": "Addition",
|
||||||
"hex.builtin.nodes.arithmetic.add.header": "Add",
|
"hex.builtin.nodes.arithmetic.add.header": "Add",
|
||||||
|
57
plugins/builtin/source/content/minimap_visualizers.cpp
Normal file
57
plugins/builtin/source/content/minimap_visualizers.cpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#include <hex/api/content_registry.hpp>
|
||||||
|
|
||||||
|
#include <imgui.h>
|
||||||
|
#include <hex/ui/imgui_imhex_extensions.h>
|
||||||
|
|
||||||
|
#include <hex/helpers/utils.hpp>
|
||||||
|
|
||||||
|
#include <wolv/utils/string.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
namespace hex::plugin::builtin {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
ImColor entropyMiniMapVisualizer(const std::vector<u8> &data) {
|
||||||
|
std::array<u32, 256> frequencies = { 0 };
|
||||||
|
for (u8 byte : data)
|
||||||
|
frequencies[byte]++;
|
||||||
|
|
||||||
|
double entropy = 0.0;
|
||||||
|
for (u32 frequency : frequencies) {
|
||||||
|
if (frequency == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
double probability = static_cast<double>(frequency) / data.size();
|
||||||
|
entropy -= probability * std::log2(probability);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate color
|
||||||
|
ImColor color = ImColor::HSV(0.0F, 0.0F, 1.0F);
|
||||||
|
|
||||||
|
if (entropy > 0.0) {
|
||||||
|
double hue = std::clamp(entropy / 8.0, 0.0, 1.0);
|
||||||
|
color = ImColor::HSV(static_cast<float>(hue) / 0.75F, 0.8F, 1.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImColor zerosMiniMapVisualizer(const std::vector<u8> &data) {
|
||||||
|
u32 zerosCount = 0;
|
||||||
|
for (u8 byte : data) {
|
||||||
|
if (byte == 0x00)
|
||||||
|
zerosCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ImColor::HSV(0.0F, 0.0F, 1.0F - (double(zerosCount) / data.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void registerMiniMapVisualizers() {
|
||||||
|
ContentRegistry::HexEditor::addMiniMapVisualizer("hex.builtin.minimap_visualizer.entropy", entropyMiniMapVisualizer);
|
||||||
|
ContentRegistry::HexEditor::addMiniMapVisualizer("hex.builtin.minimap_visualizer.zeros", zerosMiniMapVisualizer);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -14,6 +14,7 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
void registerEventHandlers();
|
void registerEventHandlers();
|
||||||
void registerDataVisualizers();
|
void registerDataVisualizers();
|
||||||
|
void registerMiniMapVisualizers();
|
||||||
void registerDataInspectorEntries();
|
void registerDataInspectorEntries();
|
||||||
void registerToolEntries();
|
void registerToolEntries();
|
||||||
void registerPatternLanguageFunctions();
|
void registerPatternLanguageFunctions();
|
||||||
@ -86,6 +87,7 @@ IMHEX_PLUGIN_SETUP("Built-in", "WerWolv", "Default ImHex functionality") {
|
|||||||
|
|
||||||
registerEventHandlers();
|
registerEventHandlers();
|
||||||
registerDataVisualizers();
|
registerDataVisualizers();
|
||||||
|
registerMiniMapVisualizers();
|
||||||
registerDataInspectorEntries();
|
registerDataInspectorEntries();
|
||||||
registerToolEntries();
|
registerToolEntries();
|
||||||
registerPatternLanguageFunctions();
|
registerPatternLanguageFunctions();
|
||||||
|
@ -100,6 +100,8 @@ namespace hex::ui {
|
|||||||
void drawEditor(const ImVec2 &size);
|
void drawEditor(const ImVec2 &size);
|
||||||
void drawFooter(const ImVec2 &size);
|
void drawFooter(const ImVec2 &size);
|
||||||
void drawTooltip(u64 address, const u8 *data, size_t size) const;
|
void drawTooltip(u64 address, const u8 *data, size_t size) const;
|
||||||
|
void drawScrollbar(ImVec2 characterSize);
|
||||||
|
void drawMinimap(ImVec2 characterSize);
|
||||||
|
|
||||||
void handleSelection(u64 address, u32 bytesPerCell, const u8 *data, bool cellHovered);
|
void handleSelection(u64 address, u32 bytesPerCell, const u8 *data, bool cellHovered);
|
||||||
std::optional<color_t> applySelectionColor(u64 byteAddress, std::optional<color_t> color);
|
std::optional<color_t> applySelectionColor(u64 byteAddress, std::optional<color_t> color);
|
||||||
@ -324,11 +326,15 @@ namespace hex::ui {
|
|||||||
bool m_shouldUpdateEditingValue = false;
|
bool m_shouldUpdateEditingValue = false;
|
||||||
std::vector<u8> m_editingBytes;
|
std::vector<u8> m_editingBytes;
|
||||||
|
|
||||||
|
std::shared_ptr<ContentRegistry::HexEditor::MiniMapVisualizer> m_miniMapVisualizer;
|
||||||
|
|
||||||
color_t m_selectionColor = 0x60C08080;
|
color_t m_selectionColor = 0x60C08080;
|
||||||
bool m_upperCaseHex = true;
|
bool m_upperCaseHex = true;
|
||||||
bool m_grayOutZero = true;
|
bool m_grayOutZero = true;
|
||||||
bool m_showAscii = true;
|
bool m_showAscii = true;
|
||||||
bool m_showCustomEncoding = true;
|
bool m_showCustomEncoding = true;
|
||||||
|
bool m_showMiniMap = false;
|
||||||
|
int m_miniMapWidth = 5;
|
||||||
bool m_showHumanReadableUnits = true;
|
bool m_showHumanReadableUnits = true;
|
||||||
u32 m_byteCellPadding = 0, m_characterCellPadding = 0;
|
u32 m_byteCellPadding = 0, m_characterCellPadding = 0;
|
||||||
bool m_footerCollapsed = true;
|
bool m_footerCollapsed = true;
|
||||||
|
@ -88,6 +88,8 @@
|
|||||||
"hex.ui.hex_editor.human_readable_units_footer": "Convert sizes to human-readable units",
|
"hex.ui.hex_editor.human_readable_units_footer": "Convert sizes to human-readable units",
|
||||||
"hex.ui.hex_editor.data_size": "Data Size",
|
"hex.ui.hex_editor.data_size": "Data Size",
|
||||||
"hex.ui.hex_editor.gray_out_zero": "Grey out zeros",
|
"hex.ui.hex_editor.gray_out_zero": "Grey out zeros",
|
||||||
|
"hex.ui.hex_editor.minimap": "Mini Map",
|
||||||
|
"hex.ui.hex_editor.minimap.width": "Width",
|
||||||
"hex.ui.hex_editor.no_bytes": "No bytes available",
|
"hex.ui.hex_editor.no_bytes": "No bytes available",
|
||||||
"hex.ui.hex_editor.page": "Page",
|
"hex.ui.hex_editor.page": "Page",
|
||||||
"hex.ui.hex_editor.region": "Region",
|
"hex.ui.hex_editor.region": "Region",
|
||||||
|
@ -72,6 +72,7 @@ namespace hex::ui {
|
|||||||
|
|
||||||
HexEditor::HexEditor(prv::Provider *provider) : m_provider(provider) {
|
HexEditor::HexEditor(prv::Provider *provider) : m_provider(provider) {
|
||||||
m_currDataVisualizer = ContentRegistry::HexEditor::getVisualizerByName("hex.builtin.visualizer.hexadecimal.8bit");
|
m_currDataVisualizer = ContentRegistry::HexEditor::getVisualizerByName("hex.builtin.visualizer.hexadecimal.8bit");
|
||||||
|
m_miniMapVisualizer = ContentRegistry::HexEditor::impl::getMiniMapVisualizers().front();
|
||||||
}
|
}
|
||||||
|
|
||||||
HexEditor::~HexEditor() {
|
HexEditor::~HexEditor() {
|
||||||
@ -150,6 +151,105 @@ namespace hex::ui {
|
|||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HexEditor::drawScrollbar(ImVec2 characterSize) {
|
||||||
|
ImS64 numRows = m_provider == nullptr ? 0 : (m_provider->getSize() / m_bytesPerRow) + ((m_provider->getSize() % m_bytesPerRow) == 0 ? 0 : 1);
|
||||||
|
|
||||||
|
auto window = ImGui::GetCurrentWindowRead();
|
||||||
|
const auto outerRect = window->Rect();
|
||||||
|
const auto innerRect = window->InnerRect;
|
||||||
|
const auto borderSize = window->WindowBorderSize;
|
||||||
|
const auto scrollbarWidth = ImGui::GetStyle().ScrollbarSize;
|
||||||
|
const auto bb = ImRect(ImMax(outerRect.Min.x, outerRect.Max.x - borderSize - scrollbarWidth), innerRect.Min.y, outerRect.Max.x, innerRect.Max.y);
|
||||||
|
|
||||||
|
constexpr auto roundingCorners = ImDrawFlags_RoundCornersTopRight | ImDrawFlags_RoundCornersBottomRight;
|
||||||
|
constexpr auto axis = ImGuiAxis_Y;
|
||||||
|
|
||||||
|
if (numRows > 0) {
|
||||||
|
ImGui::PushID("MainScrollBar");
|
||||||
|
ImGui::ScrollbarEx(
|
||||||
|
bb,
|
||||||
|
ImGui::GetWindowScrollbarID(window, axis),
|
||||||
|
axis,
|
||||||
|
&m_scrollPosition.get(),
|
||||||
|
(std::ceil(innerRect.Max.y - innerRect.Min.y) / characterSize.y),
|
||||||
|
std::nextafterf(numRows + ImGui::GetWindowSize().y / characterSize.y, std::numeric_limits<float>::max()),
|
||||||
|
roundingCorners);
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_showMiniMap && m_miniMapVisualizer != nullptr)
|
||||||
|
this->drawMinimap(characterSize);
|
||||||
|
|
||||||
|
if (ImGui::IsWindowHovered()) {
|
||||||
|
m_scrollPosition += ImS64(ImGui::GetIO().MouseWheel * -5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_scrollPosition < 0)
|
||||||
|
m_scrollPosition = 0;
|
||||||
|
if (m_scrollPosition > (numRows - 1))
|
||||||
|
m_scrollPosition = numRows - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HexEditor::drawMinimap(ImVec2 characterSize) {
|
||||||
|
ImS64 numRows = m_provider == nullptr ? 0 : (m_provider->getSize() / m_bytesPerRow) + ((m_provider->getSize() % m_bytesPerRow) == 0 ? 0 : 1);
|
||||||
|
|
||||||
|
auto window = ImGui::GetCurrentWindowRead();
|
||||||
|
const auto outerRect = window->Rect();
|
||||||
|
const auto innerRect = window->InnerRect;
|
||||||
|
const auto borderSize = window->WindowBorderSize;
|
||||||
|
const auto scrollbarWidth = ImGui::GetStyle().ScrollbarSize;
|
||||||
|
const auto bb = ImRect(ImMax(outerRect.Min.x, outerRect.Max.x - borderSize - scrollbarWidth) - scrollbarWidth * (1 + m_miniMapWidth), innerRect.Min.y, outerRect.Max.x - scrollbarWidth, innerRect.Max.y);
|
||||||
|
|
||||||
|
constexpr auto roundingCorners = ImDrawFlags_RoundCornersTopRight | ImDrawFlags_RoundCornersBottomRight;
|
||||||
|
constexpr auto axis = ImGuiAxis_Y;
|
||||||
|
|
||||||
|
constexpr static u64 RowCount = 256;
|
||||||
|
const auto rowHeight = innerRect.GetSize().y / RowCount;
|
||||||
|
const auto scrollPos = m_scrollPosition.get();
|
||||||
|
const auto grabSize = rowHeight * m_visibleRowCount;
|
||||||
|
const auto grabPos = (RowCount - m_visibleRowCount) * (double(scrollPos) / numRows);
|
||||||
|
|
||||||
|
auto drawList = ImGui::GetWindowDrawList();
|
||||||
|
|
||||||
|
drawList->ChannelsSplit(2);
|
||||||
|
drawList->ChannelsSetCurrent(1);
|
||||||
|
if (numRows > 0) {
|
||||||
|
ImGui::PushID("MiniMapScrollBar");
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, grabSize);
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_ScrollbarRounding, 0);
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrab, ImGui::GetColorU32(ImGuiCol_ScrollbarGrab, 0.4F));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabActive, ImGui::GetColorU32(ImGuiCol_ScrollbarGrabActive, 0.5F));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabHovered, ImGui::GetColorU32(ImGuiCol_ScrollbarGrabHovered, 0.5F));
|
||||||
|
ImGui::ScrollbarEx(
|
||||||
|
bb,
|
||||||
|
ImGui::GetWindowScrollbarID(window, axis),
|
||||||
|
axis,
|
||||||
|
&m_scrollPosition.get(),
|
||||||
|
(std::ceil(innerRect.Max.y - innerRect.Min.y) / characterSize.y),
|
||||||
|
std::nextafterf((numRows - m_visibleRowCount) + ImGui::GetWindowSize().y / characterSize.y, std::numeric_limits<float>::max()),
|
||||||
|
roundingCorners);
|
||||||
|
ImGui::PopStyleVar(2);
|
||||||
|
ImGui::PopStyleColor(3);
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
drawList->ChannelsSetCurrent(0);
|
||||||
|
|
||||||
|
std::vector<u8> rowData(m_bytesPerRow);
|
||||||
|
const auto drawStart = scrollPos - grabPos;
|
||||||
|
for (u64 y = drawStart; y < std::min<u64>(drawStart + RowCount, m_provider->getSize() / m_bytesPerRow); y += 1) {
|
||||||
|
const auto rowStart = bb.Min + ImVec2(0, (y - drawStart) * rowHeight);
|
||||||
|
const auto rowEnd = rowStart + ImVec2(bb.GetSize().x, rowHeight);
|
||||||
|
|
||||||
|
m_provider->read(y * m_bytesPerRow + m_provider->getBaseAddress() + m_provider->getCurrentPageAddress(), rowData.data(), rowData.size());
|
||||||
|
|
||||||
|
drawList->AddRectFilled(rowStart, rowEnd, m_miniMapVisualizer->callback(rowData));
|
||||||
|
}
|
||||||
|
|
||||||
|
drawList->ChannelsMerge();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void HexEditor::drawCell(u64 address, const u8 *data, size_t size, bool hovered, CellType cellType) {
|
void HexEditor::drawCell(u64 address, const u8 *data, size_t size, bool hovered, CellType cellType) {
|
||||||
static DataVisualizerAscii asciiVisualizer;
|
static DataVisualizerAscii asciiVisualizer;
|
||||||
|
|
||||||
@ -313,39 +413,7 @@ namespace hex::ui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::BeginChild("Hex View", size, ImGuiChildFlags_None, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) {
|
if (ImGui::BeginChild("Hex View", size, ImGuiChildFlags_None, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) {
|
||||||
// Draw scrollbar
|
this->drawScrollbar(CharacterSize);
|
||||||
{
|
|
||||||
const auto window = ImGui::GetCurrentWindowRead();
|
|
||||||
const auto axis = ImGuiAxis_Y;
|
|
||||||
ImS64 numRows = m_provider == nullptr ? 0 : (m_provider->getSize() / m_bytesPerRow) + ((m_provider->getSize() % m_bytesPerRow) == 0 ? 0 : 1);
|
|
||||||
|
|
||||||
const auto outerRect = window->Rect();
|
|
||||||
const auto innerRect = window->InnerRect;
|
|
||||||
const auto borderSize = window->WindowBorderSize;
|
|
||||||
const auto scrollbarWidth = ImGui::GetStyle().ScrollbarSize;
|
|
||||||
const auto bb = ImRect(ImMax(outerRect.Min.x, outerRect.Max.x - borderSize - scrollbarWidth), innerRect.Min.y, outerRect.Max.x, innerRect.Max.y);
|
|
||||||
const auto roundingCorners = ImDrawFlags_RoundCornersTopRight | ImDrawFlags_RoundCornersBottomRight;
|
|
||||||
|
|
||||||
if (numRows > 0) {
|
|
||||||
ImGui::ScrollbarEx(
|
|
||||||
bb,
|
|
||||||
ImGui::GetWindowScrollbarID(window, axis),
|
|
||||||
axis,
|
|
||||||
&m_scrollPosition.get(),
|
|
||||||
(std::ceil(innerRect.Max.y - innerRect.Min.y) / CharacterSize.y),
|
|
||||||
std::nextafterf(numRows + ImGui::GetWindowSize().y / CharacterSize.y, std::numeric_limits<float>::max()),
|
|
||||||
roundingCorners);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::IsWindowHovered()) {
|
|
||||||
m_scrollPosition += ImS64(ImGui::GetIO().MouseWheel * -5);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_scrollPosition < 0)
|
|
||||||
m_scrollPosition = 0;
|
|
||||||
if (m_scrollPosition > (numRows - 1))
|
|
||||||
m_scrollPosition = numRows - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(0.5, 0));
|
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(0.5, 0));
|
||||||
if (ImGui::BeginTable("##hex", byteColumnCount, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoKeepColumnsVisible, size)) {
|
if (ImGui::BeginTable("##hex", byteColumnCount, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoKeepColumnsVisible, size)) {
|
||||||
@ -850,9 +918,33 @@ namespace hex::ui {
|
|||||||
// Custom encoding view
|
// Custom encoding view
|
||||||
ImGui::BeginDisabled(!m_currCustomEncoding.has_value());
|
ImGui::BeginDisabled(!m_currCustomEncoding.has_value());
|
||||||
ImGuiExt::DimmedIconToggle(ICON_VS_WHITESPACE, &m_showCustomEncoding);
|
ImGuiExt::DimmedIconToggle(ICON_VS_WHITESPACE, &m_showCustomEncoding);
|
||||||
|
ImGuiExt::InfoTooltip("hex.ui.hex_editor.custom_encoding_view"_lang);
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
|
|
||||||
ImGuiExt::InfoTooltip("hex.ui.hex_editor.custom_encoding_view"_lang);
|
ImGui::SameLine(0, 1_scaled);
|
||||||
|
|
||||||
|
// Minimap
|
||||||
|
ImGuiExt::DimmedIconToggle(ICON_VS_MAP, &m_showMiniMap);
|
||||||
|
ImGuiExt::InfoTooltip("hex.ui.hex_editor.minimap"_lang);
|
||||||
|
if (ImGui::IsItemClicked(ImGuiMouseButton_Right) && m_miniMapVisualizer != nullptr)
|
||||||
|
ImGui::OpenPopup("MiniMapOptions");
|
||||||
|
|
||||||
|
if (ImGui::BeginPopup("MiniMapOptions")) {
|
||||||
|
ImGui::SliderInt("hex.ui.hex_editor.minimap.width"_lang, &m_miniMapWidth, 1, 25, "%d", ImGuiSliderFlags_AlwaysClamp);
|
||||||
|
|
||||||
|
if (ImGui::BeginCombo("##minimap_visualizer", Lang(m_miniMapVisualizer->unlocalizedName))) {
|
||||||
|
|
||||||
|
for (const auto &visualizer : ContentRegistry::HexEditor::impl::getMiniMapVisualizers()) {
|
||||||
|
if (ImGui::Selectable(Lang(visualizer->unlocalizedName))) {
|
||||||
|
m_miniMapVisualizer = visualizer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user