1
0
mirror of synced 2024-11-28 17:40:51 +01:00

ui: Display array patterns in pattern data view in chunks of 512 entries

This commit is contained in:
WerWolv 2022-09-19 14:16:23 +02:00
parent 814c595c12
commit 9893e7a965
3 changed files with 53 additions and 55 deletions

@ -1 +1 @@
Subproject commit 955f88b8e9673dbc98c9873965a65d7691eea1dc
Subproject commit 71669fe5f986d0f206a48ef76c8b0168a7c8c0ce

View File

@ -6,11 +6,6 @@
namespace hex {
template<typename T>
concept ArrayPattern = requires(u64 displayEnd, T pattern, std::function<void(int, pl::ptrn::Pattern&)> fn) {
{ pattern.forEachArrayEntry(displayEnd, fn) } -> std::same_as<void>;
};
class PatternDrawer : public pl::PatternVisitor {
public:
PatternDrawer() = default;
@ -36,24 +31,10 @@ namespace hex {
private:
void draw(pl::ptrn::Pattern& pattern);
template<ArrayPattern T>
void drawArray(T& pattern) {
bool opened = this->drawArrayRoot(pattern, pattern.getEntryCount(), pattern.isInlined());
if (opened) {
auto& displayEnd = this->getDisplayEnd(pattern);
pattern.forEachArrayEntry(displayEnd, [&] (u64 idx, auto &entry){
this->drawArrayNode(idx, displayEnd, entry);
});
}
this->drawArrayEnd(pattern, opened, pattern.isInlined());
}
bool drawArrayRoot(pl::ptrn::Pattern& pattern, size_t entryCount, bool isInlined);
void drawArrayNode(u64 idx, u64& displayEnd, pl::ptrn::Pattern& pattern);
void drawArrayEnd(pl::ptrn::Pattern& pattern, bool opened, bool inlined);
constexpr static auto ChunkSize = 512;
constexpr static auto DisplayEndStep = 64;
void drawArray(pl::ptrn::Pattern& pattern, pl::ptrn::Iteratable &iteratable, bool isInlined);
u64& getDisplayEnd(const pl::ptrn::Pattern& pattern);
private:

View File

@ -119,12 +119,14 @@ namespace hex {
}
void PatternDrawer::visit(pl::ptrn::PatternArrayDynamic& pattern) {
this->drawArray(pattern);
drawArray(pattern, pattern, pattern.isInlined());
}
void PatternDrawer::visit(pl::ptrn::PatternArrayStatic& pattern) {
this->drawArray(pattern);
drawArray(pattern, pattern, pattern.isInlined());
}
void PatternDrawer::visit(pl::ptrn::PatternBitfieldField& pattern) {
@ -272,8 +274,8 @@ namespace hex {
}
if (open) {
pattern.forEachMember([&](auto &member){
this->draw(member);
pattern.forEachEntry(0, pattern.getMembers().size(), [&](u64, auto *member){
this->draw(*member);
});
if (!pattern.isInlined())
@ -302,8 +304,8 @@ namespace hex {
}
if (open) {
pattern.forEachMember([&](auto &member) {
this->draw(member);
pattern.forEachEntry(0, pattern.getEntryCount(), [&](u64, auto *member) {
this->draw(*member);
});
if (!pattern.isInlined())
@ -331,9 +333,9 @@ namespace hex {
pattern.accept(*this);
}
bool PatternDrawer::drawArrayRoot(pl::ptrn::Pattern& pattern, size_t entryCount, bool isInlined) {
if (entryCount == 0)
return false;
void PatternDrawer::drawArray(pl::ptrn::Pattern& pattern, pl::ptrn::Iteratable &iteratable, bool isInlined) {
if (iteratable.getEntryCount() == 0)
return;
bool open = true;
if (!isInlined) {
@ -354,7 +356,7 @@ namespace hex {
ImGui::TextUnformatted("[");
ImGui::SameLine(0, 0);
ImGui::TextFormattedColored(ImColor(0xFF00FF00), "{0}", entryCount);
ImGui::TextFormattedColored(ImColor(0xFF00FF00), "{0}", iteratable.getEntryCount());
ImGui::SameLine(0, 0);
ImGui::TextUnformatted("]");
@ -362,35 +364,50 @@ namespace hex {
ImGui::TextFormatted("{}", pattern.getFormattedValue());
}
return open;
}
void PatternDrawer::drawArrayNode(u64 idx, u64& displayEnd, pl::ptrn::Pattern& pattern) {
u64 lastVisible = displayEnd - 1;
ImGui::PushID(reinterpret_cast<void*>(pattern.getOffset()));
if (idx < lastVisible) {
this->draw(pattern);
} else if (idx == lastVisible) {
if (open) {
u64 chunkCount = 0;
for (u64 i = 0; i < iteratable.getEntryCount(); i += ChunkSize) {
ImGui::TableNextRow();
ImGui::TableNextColumn();
chunkCount++;
auto &displayEnd = this->getDisplayEnd(pattern);
if (chunkCount > displayEnd) {
ImGui::Selectable("... (Double-click to see more items)", false, ImGuiSelectableFlags_SpanAllColumns);
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
displayEnd += DisplayEndStep;
}
ImGui::PopID();
}
void PatternDrawer::drawArrayEnd(pl::ptrn::Pattern& pattern, bool opened, bool inlined) {
if (opened) {
if (!inlined)
ImGui::TreePop();
break;
} else {
auto& displayEnd = this->getDisplayEnd(pattern);
displayEnd = DisplayEndDefault;
auto endIndex = std::min(iteratable.getEntryCount(), i + ChunkSize);
auto startOffset = iteratable.getEntry(i)->getOffset();
auto endOffset = iteratable.getEntry(endIndex - 1)->getOffset();
auto endSize = iteratable.getEntry(endIndex - 1)->getSize();
size_t chunkSize = (endOffset - startOffset) + endSize;
auto chunkOpen = ImGui::TreeNode(hex::format("[{} ... {}]", i, endIndex - 1).c_str());
ImGui::TableNextColumn();
drawColorColumn(pattern);
ImGui::TextFormatted("0x{0:08X} : 0x{1:08X}", startOffset, startOffset + chunkSize - (pattern.getSize() == 0 ? 0 : 1));
ImGui::TableNextColumn();
ImGui::TextFormatted("0x{0:04X}", chunkSize);
ImGui::TableNextColumn();
ImGui::TableNextColumn();
if (chunkOpen) {
iteratable.forEachEntry(i, endIndex, [&](u64, auto *entry){
this->draw(*entry);
});
ImGui::TreePop();
}
}
}
if (!isInlined)
ImGui::TreePop();
}
}