1
0
mirror of synced 2025-01-11 05:42:15 +01:00

feat: Added context menu and next/previous buttons to the data inspector

This commit is contained in:
WerWolv 2024-12-30 12:07:21 +01:00
parent f0525d6463
commit cb09cf3734
3 changed files with 67 additions and 9 deletions

View File

@ -24,6 +24,7 @@ namespace hex::plugin::builtin {
ContentRegistry::DataInspector::impl::DisplayFunction displayFunction;
std::optional<ContentRegistry::DataInspector::impl::EditingFunction> editingFunction;
bool editing;
u64 requiredSize;
std::string filterValue;
};
@ -62,6 +63,7 @@ namespace hex::plugin::builtin {
pl::PatternLanguage m_runtime;
std::vector<InspectorCacheEntry> m_cachedData, m_workData;
std::optional<UnlocalizedString> m_selectedEntryName;
TaskHolder m_updateTask;

View File

@ -717,6 +717,8 @@
"hex.builtin.view.constants.row.desc": "Description",
"hex.builtin.view.constants.row.name": "Name",
"hex.builtin.view.constants.row.value": "Value",
"hex.builtin.view.data_inspector.menu.copy": "Copy Value",
"hex.builtin.view.data_inspector.menu.edit": "Edit Value",
"hex.builtin.view.data_inspector.execution_error": "Custom row evaluation error",
"hex.builtin.view.data_inspector.invert": "Invert",
"hex.builtin.view.data_inspector.name": "Data Inspector",

View File

@ -91,6 +91,7 @@ namespace hex::plugin::builtin {
entry.generatorFunction(buffer, m_endian, m_numberDisplayStyle),
entry.editingFunction,
false,
entry.requiredSize,
entry.unlocalizedName
);
}
@ -160,12 +161,13 @@ namespace hex::plugin::builtin {
auto displayFunction = createPatternErrorDisplayFunction();
// Insert the inspector into the list
// Insert the inspector containing the error message into the list
m_workData.emplace_back(
wolv::util::toUTF8String(path.filename()),
std::move(displayFunction),
std::nullopt,
false,
0,
wolv::util::toUTF8String(path)
);
@ -215,6 +217,7 @@ namespace hex::plugin::builtin {
displayFunction,
editingFunction,
false,
pattern->getSize(),
wolv::util::toUTF8String(path) + ":" + pattern->getVariableName()
);
@ -223,12 +226,13 @@ namespace hex::plugin::builtin {
} catch (const pl::core::err::EvaluatorError::Exception &) {
auto displayFunction = createPatternErrorDisplayFunction();
// Insert the inspector into the list
// Insert the inspector containing the error message into the list
m_workData.emplace_back(
wolv::util::toUTF8String(path.filename()),
std::move(displayFunction),
std::nullopt,
false,
0,
wolv::util::toUTF8String(path)
);
}
@ -260,6 +264,36 @@ namespace hex::plugin::builtin {
});
}
const auto selection = ImHexApi::HexEditor::getSelection();
const auto selectedEntryIt = std::find_if(m_cachedData.begin(), m_cachedData.end(), [this](const InspectorCacheEntry &entry) {
return entry.unlocalizedName == m_selectedEntryName;
});
u64 requiredSize = selectedEntryIt == m_cachedData.end() ? 0x00 : selectedEntryIt->requiredSize;
ImGui::BeginDisabled(!selection.has_value() || !m_selectedEntryName.has_value());
{
const auto buttonSize = ImVec2((ImGui::GetContentRegionAvail().x / 2) - ImGui::GetStyle().FramePadding.x, 0);
const auto baseAddress = m_selectedProvider->getBaseAddress();
const auto providerSize = m_selectedProvider->getActualSize();
const auto providerEndAddress = baseAddress + providerSize;
ImGui::BeginDisabled(providerSize < requiredSize || selection->getStartAddress() < baseAddress + requiredSize);
if (ImGuiExt::DimmedIconButton(ICON_VS_ARROW_LEFT, ImGui::GetStyleColorVec4(ImGuiCol_Text), buttonSize)) {
ImHexApi::HexEditor::setSelection(Region { selection->getStartAddress() - requiredSize, requiredSize });
}
ImGui::EndDisabled();
ImGui::SameLine();
ImGui::BeginDisabled(providerSize < requiredSize || selection->getEndAddress() > providerEndAddress - requiredSize);
if (ImGuiExt::DimmedIconButton(ICON_VS_ARROW_RIGHT, ImGui::GetStyleColorVec4(ImGuiCol_Text), buttonSize)) {
ImHexApi::HexEditor::setSelection(Region { selection->getStartAddress() + requiredSize, requiredSize });
}
ImGui::EndDisabled();
}
ImGui::EndDisabled();
if (ImGui::BeginTable("##datainspector", m_tableEditingModeEnabled ? 3 : 2,
ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg,
ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * (validLineCount + 1)))) {
@ -379,16 +413,36 @@ namespace hex::plugin::builtin {
ImGui::SameLine();
// Handle copying the value to the clipboard when clicking the row
if (ImGui::Selectable("##InspectorLine", false, ImGuiSelectableFlags_SpanAllColumns |
ImGuiSelectableFlags_AllowOverlap)) {
ImGui::SetClipboardText(copyValue.c_str());
if (ImGui::Selectable("##InspectorLine", m_selectedEntryName == entry.unlocalizedName, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap)) {
m_selectedEntryName = entry.unlocalizedName;
if (auto selection = ImHexApi::HexEditor::getSelection(); selection.has_value()) {
ImHexApi::HexEditor::setSelection(Region { selection->getStartAddress(), entry.requiredSize });
}
}
// Enter editing mode when double-clicking the row
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) &&
entry.editingFunction.has_value() && m_selectedProvider->isWritable()) {
entry.editing = true;
m_editingValue = copyValue;
const bool editable = entry.editingFunction.has_value() && m_selectedProvider->isWritable();
if (ImGui::IsItemHovered()) {
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) && editable) {
entry.editing = true;
m_editingValue = copyValue;
m_selectedEntryName.reset();
}
if (ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
ImGui::OpenPopup("##InspectorMenu");
}
}
if (ImGui::BeginPopup("##InspectorMenu")) {
if (ImGui::MenuItemEx("hex.builtin.view.data_inspector.menu.copy"_lang, ICON_VS_COPY)) {
ImGui::SetClipboardText(copyValue.c_str());
}
if (ImGui::MenuItemEx("hex.builtin.view.data_inspector.menu.edit"_lang, ICON_VS_EDIT, nullptr, false, editable)) {
entry.editing = true;
m_editingValue = copyValue;
m_selectedEntryName.reset();
}
ImGui::EndPopup();
}
return;