feat: Added context menu and next/previous buttons to the data inspector
This commit is contained in:
parent
f0525d6463
commit
cb09cf3734
@ -24,6 +24,7 @@ namespace hex::plugin::builtin {
|
|||||||
ContentRegistry::DataInspector::impl::DisplayFunction displayFunction;
|
ContentRegistry::DataInspector::impl::DisplayFunction displayFunction;
|
||||||
std::optional<ContentRegistry::DataInspector::impl::EditingFunction> editingFunction;
|
std::optional<ContentRegistry::DataInspector::impl::EditingFunction> editingFunction;
|
||||||
bool editing;
|
bool editing;
|
||||||
|
u64 requiredSize;
|
||||||
|
|
||||||
std::string filterValue;
|
std::string filterValue;
|
||||||
};
|
};
|
||||||
@ -62,6 +63,7 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
pl::PatternLanguage m_runtime;
|
pl::PatternLanguage m_runtime;
|
||||||
std::vector<InspectorCacheEntry> m_cachedData, m_workData;
|
std::vector<InspectorCacheEntry> m_cachedData, m_workData;
|
||||||
|
std::optional<UnlocalizedString> m_selectedEntryName;
|
||||||
|
|
||||||
TaskHolder m_updateTask;
|
TaskHolder m_updateTask;
|
||||||
|
|
||||||
|
@ -717,6 +717,8 @@
|
|||||||
"hex.builtin.view.constants.row.desc": "Description",
|
"hex.builtin.view.constants.row.desc": "Description",
|
||||||
"hex.builtin.view.constants.row.name": "Name",
|
"hex.builtin.view.constants.row.name": "Name",
|
||||||
"hex.builtin.view.constants.row.value": "Value",
|
"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.execution_error": "Custom row evaluation error",
|
||||||
"hex.builtin.view.data_inspector.invert": "Invert",
|
"hex.builtin.view.data_inspector.invert": "Invert",
|
||||||
"hex.builtin.view.data_inspector.name": "Data Inspector",
|
"hex.builtin.view.data_inspector.name": "Data Inspector",
|
||||||
|
@ -91,6 +91,7 @@ namespace hex::plugin::builtin {
|
|||||||
entry.generatorFunction(buffer, m_endian, m_numberDisplayStyle),
|
entry.generatorFunction(buffer, m_endian, m_numberDisplayStyle),
|
||||||
entry.editingFunction,
|
entry.editingFunction,
|
||||||
false,
|
false,
|
||||||
|
entry.requiredSize,
|
||||||
entry.unlocalizedName
|
entry.unlocalizedName
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -160,12 +161,13 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
auto displayFunction = createPatternErrorDisplayFunction();
|
auto displayFunction = createPatternErrorDisplayFunction();
|
||||||
|
|
||||||
// Insert the inspector into the list
|
// Insert the inspector containing the error message into the list
|
||||||
m_workData.emplace_back(
|
m_workData.emplace_back(
|
||||||
wolv::util::toUTF8String(path.filename()),
|
wolv::util::toUTF8String(path.filename()),
|
||||||
std::move(displayFunction),
|
std::move(displayFunction),
|
||||||
std::nullopt,
|
std::nullopt,
|
||||||
false,
|
false,
|
||||||
|
0,
|
||||||
wolv::util::toUTF8String(path)
|
wolv::util::toUTF8String(path)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -215,6 +217,7 @@ namespace hex::plugin::builtin {
|
|||||||
displayFunction,
|
displayFunction,
|
||||||
editingFunction,
|
editingFunction,
|
||||||
false,
|
false,
|
||||||
|
pattern->getSize(),
|
||||||
wolv::util::toUTF8String(path) + ":" + pattern->getVariableName()
|
wolv::util::toUTF8String(path) + ":" + pattern->getVariableName()
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -223,12 +226,13 @@ namespace hex::plugin::builtin {
|
|||||||
} catch (const pl::core::err::EvaluatorError::Exception &) {
|
} catch (const pl::core::err::EvaluatorError::Exception &) {
|
||||||
auto displayFunction = createPatternErrorDisplayFunction();
|
auto displayFunction = createPatternErrorDisplayFunction();
|
||||||
|
|
||||||
// Insert the inspector into the list
|
// Insert the inspector containing the error message into the list
|
||||||
m_workData.emplace_back(
|
m_workData.emplace_back(
|
||||||
wolv::util::toUTF8String(path.filename()),
|
wolv::util::toUTF8String(path.filename()),
|
||||||
std::move(displayFunction),
|
std::move(displayFunction),
|
||||||
std::nullopt,
|
std::nullopt,
|
||||||
false,
|
false,
|
||||||
|
0,
|
||||||
wolv::util::toUTF8String(path)
|
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,
|
if (ImGui::BeginTable("##datainspector", m_tableEditingModeEnabled ? 3 : 2,
|
||||||
ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg,
|
ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg,
|
||||||
ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * (validLineCount + 1)))) {
|
ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * (validLineCount + 1)))) {
|
||||||
@ -379,16 +413,36 @@ namespace hex::plugin::builtin {
|
|||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
// Handle copying the value to the clipboard when clicking the row
|
// Handle copying the value to the clipboard when clicking the row
|
||||||
if (ImGui::Selectable("##InspectorLine", false, ImGuiSelectableFlags_SpanAllColumns |
|
if (ImGui::Selectable("##InspectorLine", m_selectedEntryName == entry.unlocalizedName, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap)) {
|
||||||
ImGuiSelectableFlags_AllowOverlap)) {
|
m_selectedEntryName = entry.unlocalizedName;
|
||||||
ImGui::SetClipboardText(copyValue.c_str());
|
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
|
// Enter editing mode when double-clicking the row
|
||||||
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) &&
|
const bool editable = entry.editingFunction.has_value() && m_selectedProvider->isWritable();
|
||||||
entry.editingFunction.has_value() && m_selectedProvider->isWritable()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
entry.editing = true;
|
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) && editable) {
|
||||||
m_editingValue = copyValue;
|
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;
|
return;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user