ui: Display array patterns in pattern data view in chunks of 512 entries
This commit is contained in:
parent
814c595c12
commit
9893e7a965
2
lib/external/pattern_language
vendored
2
lib/external/pattern_language
vendored
@ -1 +1 @@
|
||||
Subproject commit 955f88b8e9673dbc98c9873965a65d7691eea1dc
|
||||
Subproject commit 71669fe5f986d0f206a48ef76c8b0168a7c8c0ce
|
@ -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:
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user