Skip to content

Commit

Permalink
feat: Added option to fit hex columns to screen width
Browse files Browse the repository at this point in the history
  • Loading branch information
WerWolv committed Dec 31, 2024
1 parent 1d64150 commit c9e8858
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 20 deletions.
2 changes: 2 additions & 0 deletions plugins/ui/include/ui/hex_editor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,8 @@ namespace hex::ui {
bool m_enteredEditingMode = false;
bool m_shouldUpdateEditingValue = false;
std::vector<u8> m_editingBytes;
u32 m_maxFittingColumns = 16;
bool m_autoFitColumns = false;

std::shared_ptr<ContentRegistry::HexEditor::MiniMapVisualizer> m_miniMapVisualizer;

Expand Down
1 change: 1 addition & 0 deletions plugins/ui/romfs/lang/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
"hex.ui.hex_editor.ascii_view": "Display ASCII column",
"hex.ui.hex_editor.custom_encoding_view": "Display advanced decoding column",
"hex.ui.hex_editor.columns": "Columns",
"hex.ui.hex_editor.fit_columns": "Fit columns to width",
"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_cell_options": "Data Cell Options",
Expand Down
57 changes: 37 additions & 20 deletions plugins/ui/source/ui/hex_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -602,14 +602,18 @@ namespace hex::ui {
ImGui::TableNextRow();
ImGui::TableNextColumn();

const auto rowAddress = y * m_bytesPerRow + m_provider->getBaseAddress() + m_provider->getCurrentPageAddress();
double addressWidth = ImGui::GetCursorPosX();
{
const auto rowAddress = y * m_bytesPerRow + m_provider->getBaseAddress() + m_provider->getCurrentPageAddress();

if (m_separatorStride > 0 && rowAddress % m_separatorStride < m_bytesPerRow && !ImGui::GetIO().KeyShift)
ImGuiExt::TextFormattedColored(ImGui::GetStyleColorVec4(ImGuiCol_SeparatorActive), "{} {}", "hex.ui.common.segment"_lang, rowAddress / m_separatorStride);
else
ImGuiExt::TextFormattedSelectable("{0}: ", formatAddress(rowAddress, 8));
if (m_separatorStride > 0 && rowAddress % m_separatorStride < m_bytesPerRow && !ImGui::GetIO().KeyShift)
ImGuiExt::TextFormattedColored(ImGui::GetStyleColorVec4(ImGuiCol_SeparatorActive), "{} {}", "hex.ui.common.segment"_lang, rowAddress / m_separatorStride);
else
ImGuiExt::TextFormattedSelectable("{0}: ", formatAddress(rowAddress, 8));
}

ImGui::TableNextColumn();
addressWidth = ImGui::GetCursorPosX() - addressWidth;

const u8 validBytes = std::min<u64>(m_bytesPerRow, m_provider->getSize() - y * m_bytesPerRow);

Expand Down Expand Up @@ -655,6 +659,10 @@ namespace hex::ui {
// Draw byte columns
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, scaled(ImVec2(2.75F, 0.0F)));

const auto maxCharsPerCell = m_currDataVisualizer->getMaxCharsPerCell();
auto byteCellSize = (CharacterSize * ImVec2(maxCharsPerCell, 1)) + (ImVec2(2, 2) * ImGui::GetStyle().CellPadding) + scaled(ImVec2(1 + m_byteCellPadding, 0));
byteCellSize = ImVec2(std::ceil(byteCellSize.x), std::ceil(byteCellSize.y));

for (u64 x = 0; x < columnCount; x++) {
const u64 byteAddress = y * m_bytesPerRow + x * bytesPerCell + m_provider->getBaseAddress() + m_provider->getCurrentPageAddress();

Expand All @@ -667,32 +675,28 @@ namespace hex::ui {

if (x < std::ceil(float(validBytes) / bytesPerCell)) {
auto cellStartPos = getCellPosition();
auto cellSize = (CharacterSize * ImVec2(m_currDataVisualizer->getMaxCharsPerCell(), 1)) + (ImVec2(2, 2) * ImGui::GetStyle().CellPadding) + scaled(ImVec2(1 + m_byteCellPadding, 0));
auto maxCharsPerCell = m_currDataVisualizer->getMaxCharsPerCell();

cellSize = ImVec2(std::ceil(cellSize.x), std::ceil(cellSize.y));

auto [foregroundColor, backgroundColor] = cellColors[x];

auto adjustedCellSize = byteCellSize;
if (isColumnSeparatorColumn(x + 1, columnCount) && cellColors.size() > x + 1) {
auto separatorAddress = x + y * columnCount;
auto [nextForegroundColor, nextBackgroundColor] = cellColors[x + 1];
if ((isSelectionValid() && getSelection().overlaps({ separatorAddress, 1 }) && getSelection().getEndAddress() != separatorAddress) || backgroundColor == nextBackgroundColor)
cellSize.x += SeparatorColumWidth + 1;
adjustedCellSize.x += SeparatorColumWidth + 1;
}

if (y == m_scrollPosition)
cellSize.y -= (ImGui::GetStyle().CellPadding.y);
adjustedCellSize.y -= (ImGui::GetStyle().CellPadding.y);

backgroundColor = applySelectionColor(byteAddress, backgroundColor);

// Draw highlights and selection
if (backgroundColor.has_value()) {
// Draw frame around mouse selection
this->drawSelectionFrame(x, y, selection, byteAddress, bytesPerCell, cellStartPos, cellSize, backgroundColor.value());
this->drawSelectionFrame(x, y, selection, byteAddress, bytesPerCell, cellStartPos, adjustedCellSize, backgroundColor.value());
}

const bool cellHovered = ImGui::IsMouseHoveringRect(cellStartPos, cellStartPos + cellSize, false) && ImGui::IsWindowHovered();
const bool cellHovered = ImGui::IsMouseHoveringRect(cellStartPos, cellStartPos + adjustedCellSize, false) && ImGui::IsWindowHovered();

this->handleSelection(byteAddress, bytesPerCell, &bytes[x * bytesPerCell], cellHovered);

Expand Down Expand Up @@ -737,16 +741,17 @@ namespace hex::ui {

ImGui::TableNextRow();

const auto asciiCellSize = CharacterSize + scaled(ImVec2(m_characterCellPadding, 0));

for (u64 x = 0; x < m_bytesPerRow; x++) {
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 cellSize = CharacterSize + scaled(ImVec2(m_characterCellPadding, 0));

const bool cellHovered = ImGui::IsMouseHoveringRect(cellStartPos, cellStartPos + cellSize, true) && ImGui::IsWindowHovered();
const bool cellHovered = ImGui::IsMouseHoveringRect(cellStartPos, cellStartPos + asciiCellSize, true) && ImGui::IsWindowHovered();

if (x < validBytes) {
this->handleSelection(byteAddress, bytesPerCell, &bytes[x], cellHovered);
Expand All @@ -757,7 +762,7 @@ namespace hex::ui {

// Draw highlights and selection
if (backgroundColor.has_value()) {
this->drawSelectionFrame(x, y, selection, byteAddress, 1, cellStartPos, cellSize, backgroundColor.value());
this->drawSelectionFrame(x, y, selection, byteAddress, 1, cellStartPos, asciiCellSize, backgroundColor.value());
}

// Set cell foreground color
Expand Down Expand Up @@ -797,6 +802,8 @@ namespace hex::ui {

// Draw Custom encoding column
if (m_showCustomEncoding && m_currCustomEncoding.has_value()) {
m_maxFittingColumns = 16;

if (m_encodingLineStartAddresses.empty()) {
m_encodingLineStartAddresses.push_back(0);
}
Expand Down Expand Up @@ -879,6 +886,10 @@ namespace hex::ui {
}
ImGui::PopStyleVar();
}
} else {
m_maxFittingColumns = std::floor((size.x - addressWidth) / (byteCellSize.x + CharacterSize.x + m_characterCellPadding * 1_scaled));
m_maxFittingColumns *= 0.95;
m_maxFittingColumns = std::clamp<i32>(m_maxFittingColumns, 1, 128 / this->getBytesPerCell());
}

// Scroll to the cursor if it's either at the top or bottom edge of the screen
Expand Down Expand Up @@ -1072,11 +1083,13 @@ namespace hex::ui {

ImGui::NewLine();

int bytesPerRow = m_bytesPerRow / this->getBytesPerCell();
if (ImGui::SliderInt("##row_size", &bytesPerRow, 1, 128 / this->getBytesPerCell(), hex::format("{} {}", bytesPerRow * this->getBytesPerCell(), "hex.ui.hex_editor.columns"_lang).c_str())) {
m_bytesPerRow = bytesPerRow * this->getBytesPerCell();
int byteColumnCount = m_autoFitColumns ? 0 : m_bytesPerRow / this->getBytesPerCell();
if (ImGui::SliderInt("##byte_column_count", &byteColumnCount, 0, 128 / this->getBytesPerCell(), m_autoFitColumns ? "hex.ui.hex_editor.fit_columns"_lang : hex::format("{} {}", byteColumnCount * this->getBytesPerCell(), "hex.ui.hex_editor.columns"_lang).c_str())) {
m_bytesPerRow = byteColumnCount * this->getBytesPerCell();
m_encodingLineStartAddresses.clear();
}
m_autoFitColumns = byteColumnCount == 0;

{
const u64 min = 0;
const u64 max = m_provider->getActualSize();
Expand Down Expand Up @@ -1196,6 +1209,10 @@ namespace hex::ui {
}
}
ImGui::EndChild();

if (m_autoFitColumns) {
m_bytesPerRow = m_maxFittingColumns * this->getBytesPerCell();
}
}

void HexEditor::handleSelection(u64 address, u32 bytesPerCell, const u8 *data, bool cellHovered) {
Expand Down

0 comments on commit c9e8858

Please sign in to comment.