1
0
mirror of synced 2025-01-22 19:42:11 +01:00

feat: Added hex editor segment separators

This commit is contained in:
WerWolv 2024-11-28 21:26:55 +01:00
parent 71f2f3a5fc
commit 9be9eb90f6
3 changed files with 47 additions and 4 deletions

View File

@ -96,6 +96,7 @@ namespace hex::ui {
enum class CellType : u8 { None, Hex, ASCII }; enum class CellType : u8 { None, Hex, ASCII };
void drawCell(u64 address, const u8 *data, size_t size, bool hovered, CellType cellType); void drawCell(u64 address, const u8 *data, size_t size, bool hovered, CellType cellType);
void drawSeparatorLine(u64 address, bool drawVerticalConnector);
void drawSelectionFrame(u32 x, u32 y, Region selection, u64 byteAddress, u16 bytesPerCell, const ImVec2 &cellPos, const ImVec2 &cellSize, const ImColor &backgroundColor) const; void drawSelectionFrame(u32 x, u32 y, Region selection, u64 byteAddress, u16 bytesPerCell, const ImVec2 &cellPos, const ImVec2 &cellSize, const ImColor &backgroundColor) const;
void drawEditor(const ImVec2 &size); void drawEditor(const ImVec2 &size);
void drawFooter(const ImVec2 &size); void drawFooter(const ImVec2 &size);
@ -339,6 +340,7 @@ namespace hex::ui {
std::endian m_dataVisualizerEndianness = std::endian::little; std::endian m_dataVisualizerEndianness = std::endian::little;
std::shared_ptr<ContentRegistry::HexEditor::DataVisualizer> m_currDataVisualizer; std::shared_ptr<ContentRegistry::HexEditor::DataVisualizer> m_currDataVisualizer;
char m_unknownDataCharacter = '?'; char m_unknownDataCharacter = '?';
u64 m_separatorStride = 0;
bool m_shouldJumpToSelection = false; bool m_shouldJumpToSelection = false;
float m_jumpPivot = 0.0F; float m_jumpPivot = 0.0F;

View File

@ -63,6 +63,7 @@
"hex.ui.common.region": "Region", "hex.ui.common.region": "Region",
"hex.ui.common.remove": "Remove", "hex.ui.common.remove": "Remove",
"hex.ui.common.reset": "Reset", "hex.ui.common.reset": "Reset",
"hex.ui.common.segment": "Segment",
"hex.ui.common.set": "Set", "hex.ui.common.set": "Set",
"hex.ui.common.settings": "Settings", "hex.ui.common.settings": "Settings",
"hex.ui.common.size": "Size", "hex.ui.common.size": "Size",
@ -97,6 +98,8 @@
"hex.ui.hex_editor.region": "Region", "hex.ui.hex_editor.region": "Region",
"hex.ui.hex_editor.selection": "Selection", "hex.ui.hex_editor.selection": "Selection",
"hex.ui.hex_editor.selection.none": "None", "hex.ui.hex_editor.selection.none": "None",
"hex.ui.hex_editor.separator_stride": "Segment Size: 0x{0:02X}",
"hex.ui.hex_editor.no_separator": "No Segment Separators",
"hex.ui.hex_editor.uppercase_hex": "Upper case Hex characters", "hex.ui.hex_editor.uppercase_hex": "Upper case Hex characters",
"hex.ui.hex_editor.visualizer": "Data visualizer", "hex.ui.hex_editor.visualizer": "Data visualizer",
"hex.ui.pattern_drawer.color": "Color", "hex.ui.pattern_drawer.color": "Color",

View File

@ -300,6 +300,7 @@ namespace hex::ui {
std::reverse(buffer.begin(), buffer.begin() + size); std::reverse(buffer.begin(), buffer.begin() + size);
m_currDataVisualizer->draw(address, buffer.data(), size, m_upperCaseHex); m_currDataVisualizer->draw(address, buffer.data(), size, m_upperCaseHex);
} else { } else {
asciiVisualizer.draw(address, data, size, m_upperCaseHex); asciiVisualizer.draw(address, data, size, m_upperCaseHex);
} }
@ -408,6 +409,26 @@ namespace hex::ui {
} }
} }
void HexEditor::drawSeparatorLine(u64 address, bool drawVerticalConnector) {
if (m_separatorStride == 0) return;
const u64 regionProgress = address % m_separatorStride;
const u64 cellsPerRow = m_bytesPerRow / m_currDataVisualizer->getBytesPerCell();
const auto table = ImGui::GetCurrentTable();
if (regionProgress < cellsPerRow) {
const auto rect = ImGui::TableGetCellBgRect(table, table->CurrentColumn);
const auto drawList = ImGui::GetWindowDrawList();
const auto lineColor = ImGui::GetColorU32(ImGuiCol_SeparatorActive);
drawList->AddLine(rect.Min, ImVec2(rect.Max.x, rect.Min.y), lineColor);
if (regionProgress == 0 && drawVerticalConnector) {
drawList->AddLine(ImFloor(rect.Min), ImFloor(ImVec2(rect.Min.x, rect.Max.y)), lineColor);
}
}
}
void HexEditor::drawSelectionFrame(u32 x, u32 y, Region selection, u64 byteAddress, u16 bytesPerCell, const ImVec2 &cellPos, const ImVec2 &cellSize, const ImColor &backgroundColor) const { void HexEditor::drawSelectionFrame(u32 x, u32 y, Region selection, u64 byteAddress, u16 bytesPerCell, const ImVec2 &cellPos, const ImVec2 &cellSize, const ImColor &backgroundColor) const {
auto drawList = ImGui::GetWindowDrawList(); auto drawList = ImGui::GetWindowDrawList();
@ -565,7 +586,14 @@ namespace hex::ui {
// Draw address column // Draw address column
ImGui::TableNextRow(); ImGui::TableNextRow();
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGuiExt::TextFormatted(m_upperCaseHex ? "{:08X}: " : "{:08x}: ", y * m_bytesPerRow + m_provider->getBaseAddress() + m_provider->getCurrentPageAddress());
const auto rowAddress = y * m_bytesPerRow + m_provider->getBaseAddress() + m_provider->getCurrentPageAddress();
if (m_separatorStride > 0 && rowAddress % m_separatorStride < m_bytesPerRow)
ImGuiExt::TextFormattedColored(ImGui::GetStyleColorVec4(ImGuiCol_SeparatorActive), "{} {}", "hex.ui.common.segment"_lang, rowAddress / m_separatorStride);
else
ImGuiExt::TextFormatted(m_upperCaseHex ? "{:08X}: " : "{:08x}: ", rowAddress);
ImGui::TableNextColumn(); ImGui::TableNextColumn();
const u8 validBytes = std::min<u64>(m_bytesPerRow, m_provider->getSize() - y * m_bytesPerRow); const u8 validBytes = std::min<u64>(m_bytesPerRow, m_provider->getSize() - y * m_bytesPerRow);
@ -616,8 +644,11 @@ namespace hex::ui {
const u64 byteAddress = y * m_bytesPerRow + x * bytesPerCell + m_provider->getBaseAddress() + m_provider->getCurrentPageAddress(); const u64 byteAddress = y * m_bytesPerRow + x * bytesPerCell + m_provider->getBaseAddress() + m_provider->getCurrentPageAddress();
ImGui::TableNextColumn(); ImGui::TableNextColumn();
if (isColumnSeparatorColumn(x, columnCount)) if (y != 0) drawSeparatorLine(byteAddress, x != 0);
if (isColumnSeparatorColumn(x, columnCount)) {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
if (y != 0) drawSeparatorLine(byteAddress, false);
}
if (x < std::ceil(float(validBytes) / bytesPerCell)) { if (x < std::ceil(float(validBytes) / bytesPerCell)) {
auto cellStartPos = getCellPosition(); auto cellStartPos = getCellPosition();
@ -679,6 +710,7 @@ namespace hex::ui {
ImGui::PopStyleVar(); ImGui::PopStyleVar();
ImGui::TableNextColumn(); ImGui::TableNextColumn();
if (y != 0) drawSeparatorLine(y * m_bytesPerRow + m_provider->getBaseAddress() + m_provider->getCurrentPageAddress(), false);
ImGui::TableNextColumn(); ImGui::TableNextColumn();
// Draw ASCII column // Draw ASCII column
@ -691,10 +723,11 @@ namespace hex::ui {
ImGui::TableNextRow(); ImGui::TableNextRow();
for (u64 x = 0; x < m_bytesPerRow; x++) { for (u64 x = 0; x < m_bytesPerRow; x++) {
ImGui::TableNextColumn();
const u64 byteAddress = y * m_bytesPerRow + x + m_provider->getBaseAddress() + m_provider->getCurrentPageAddress(); const u64 byteAddress = y * m_bytesPerRow + x + m_provider->getBaseAddress() + m_provider->getCurrentPageAddress();
ImGui::TableNextColumn();
if (y != 0) drawSeparatorLine(byteAddress, true);
const auto cellStartPos = getCellPosition(); const auto cellStartPos = getCellPosition();
const auto cellSize = CharacterSize + scaled(ImVec2(m_characterCellPadding, 0)); const auto cellSize = CharacterSize + scaled(ImVec2(m_characterCellPadding, 0));
@ -1029,6 +1062,11 @@ namespace hex::ui {
m_bytesPerRow = bytesPerRow * this->getBytesPerCell(); m_bytesPerRow = bytesPerRow * this->getBytesPerCell();
m_encodingLineStartAddresses.clear(); m_encodingLineStartAddresses.clear();
} }
{
const auto min = 0;
const auto max = m_provider->getActualSize();
ImGui::SliderScalar("##separator_stride", ImGuiDataType_U64, &m_separatorStride, &min, &max, m_separatorStride == 0 ? "hex.ui.hex_editor.no_separator"_lang : hex::format("hex.ui.hex_editor.separator_stride"_lang, m_separatorStride).c_str());
}
ImGui::EndPopup(); ImGui::EndPopup();
} }
} }