1
0
mirror of synced 2025-01-30 19:43:43 +01:00

impr: Return early to remove nested code (#1253)

<!--
Please provide as much information as possible about what your PR aims
to do.
PRs with no description will most likely be closed until more
information is provided.
If you're planing on changing fundamental behaviour or add big new
features, please open a GitHub Issue first before starting to work on
it.
If it's not something big and you still want to contact us about it,
feel free to do so !
-->

### Problem description
<!-- Describe the bug that you fixed/feature request that you
implemented, or link to an existing issue describing it -->
This will simplify the codebase in the pattern drawer. It returns early
on conditional statements and reduces the amount of nested code making
it easier to read and track while developing.
This commit is contained in:
Paul Sorensen 2023-09-20 04:49:09 -04:00 committed by GitHub
parent c577a42f62
commit be8c679d4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -109,25 +109,27 @@ namespace hex::plugin::builtin::ui {
} }
void drawOffsetColumn(const pl::ptrn::Pattern& pattern) { void drawOffsetColumn(const pl::ptrn::Pattern& pattern) {
if (auto *bitfieldMember = dynamic_cast<pl::ptrn::PatternBitfieldMember const*>(&pattern); bitfieldMember != nullptr && bitfieldMember->getParentBitfield() != nullptr) auto *bitfieldMember = dynamic_cast<pl::ptrn::PatternBitfieldMember const*>(&pattern);
if (bitfieldMember != nullptr && bitfieldMember->getParentBitfield() != nullptr) {
drawOffsetColumnForBitfieldMember(*bitfieldMember); drawOffsetColumnForBitfieldMember(*bitfieldMember);
else { return;
if (pattern.isPatternLocal()) {
ImGui::TextFormatted("[{}]", "hex.builtin.pattern_drawer.local"_lang);
} else {
ImGui::TextFormatted("0x{0:08X}", pattern.getOffset());
}
ImGui::TableNextColumn();
if (pattern.isPatternLocal()) {
ImGui::TextFormatted("[{}]", "hex.builtin.pattern_drawer.local"_lang);
} else {
ImGui::TextFormatted("0x{0:08X}", pattern.getOffset() + pattern.getSize() - (pattern.getSize() == 0 ? 0 : 1));
}
ImGui::TableNextColumn();
} }
if (pattern.isPatternLocal()) {
ImGui::TextFormatted("[{}]", "hex.builtin.pattern_drawer.local"_lang);
} else {
ImGui::TextFormatted("0x{0:08X}", pattern.getOffset());
}
ImGui::TableNextColumn();
if (pattern.isPatternLocal()) {
ImGui::TextFormatted("[{}]", "hex.builtin.pattern_drawer.local"_lang);
} else {
ImGui::TextFormatted("0x{0:08X}", pattern.getOffset() + pattern.getSize() - (pattern.getSize() == 0 ? 0 : 1));
}
ImGui::TableNextColumn();
} }
inline void drawSizeColumnForBitfieldMember(const pl::ptrn::PatternBitfieldMember &pattern) { inline void drawSizeColumnForBitfieldMember(const pl::ptrn::PatternBitfieldMember &pattern) {
@ -155,17 +157,19 @@ namespace hex::plugin::builtin::ui {
std::vector<std::string> parseRValueFilter(const std::string &filter) { std::vector<std::string> parseRValueFilter(const std::string &filter) {
std::vector<std::string> result; std::vector<std::string> result;
if (!filter.empty()) { if (filter.empty()) {
result.emplace_back(); return result;
for (char c : filter) { }
if (c == '.')
result.emplace_back(); result.emplace_back();
else if (c == '[') { for (char c : filter) {
result.emplace_back(); if (c == '.')
result.back() += c; result.emplace_back();
} else { else if (c == '[') {
result.back() += c; result.emplace_back();
} result.back() += c;
} else {
result.back() += c;
} }
} }
@ -203,23 +207,26 @@ namespace hex::plugin::builtin::ui {
} }
void PatternDrawer::drawFavoriteColumn(const pl::ptrn::Pattern& pattern) { void PatternDrawer::drawFavoriteColumn(const pl::ptrn::Pattern& pattern) {
if (this->m_showFavoriteStars) { if (!this->m_showFavoriteStars) {
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0)); ImGui::TableNextColumn();
return;
if (this->m_favorites.contains(this->m_currPatternPath)) {
if (ImGui::DimmedIconButton(ICON_VS_STAR_DELETE, ImGui::GetStyleColorVec4(ImGuiCol_PlotHistogram))) {
this->m_favorites.erase(this->m_currPatternPath);
}
}
else {
if (ImGui::DimmedIconButton(ICON_VS_STAR_ADD, ImGui::GetStyleColorVec4(ImGuiCol_TextDisabled))) {
this->m_favorites.insert({ this->m_currPatternPath, pattern.clone() });
}
}
ImGui::PopStyleVar();
} }
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
if (this->m_favorites.contains(this->m_currPatternPath)) {
if (ImGui::DimmedIconButton(ICON_VS_STAR_DELETE, ImGui::GetStyleColorVec4(ImGuiCol_PlotHistogram))) {
this->m_favorites.erase(this->m_currPatternPath);
}
}
else {
if (ImGui::DimmedIconButton(ICON_VS_STAR_ADD, ImGui::GetStyleColorVec4(ImGuiCol_TextDisabled))) {
this->m_favorites.insert({ this->m_currPatternPath, pattern.clone() });
}
}
ImGui::PopStyleVar();
ImGui::TableNextColumn(); ImGui::TableNextColumn();
} }
@ -305,20 +312,19 @@ namespace hex::plugin::builtin::ui {
ImGui::Unindent(); ImGui::Unindent();
return false; return false;
} }
else {
return highlightWhenSelected(pattern, [&]{ return highlightWhenSelected(pattern, [&]{
switch (this->m_treeStyle) { switch (this->m_treeStyle) {
using enum TreeStyle; using enum TreeStyle;
default: default:
case Default: case Default:
return ImGui::TreeNodeEx(this->getDisplayName(pattern).c_str(), ImGuiTreeNodeFlags_SpanFullWidth); return ImGui::TreeNodeEx(this->getDisplayName(pattern).c_str(), ImGuiTreeNodeFlags_SpanFullWidth);
case AutoExpanded: case AutoExpanded:
return ImGui::TreeNodeEx(this->getDisplayName(pattern).c_str(), ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_DefaultOpen); return ImGui::TreeNodeEx(this->getDisplayName(pattern).c_str(), ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_DefaultOpen);
case Flattened: case Flattened:
return ImGui::TreeNodeEx(this->getDisplayName(pattern).c_str(), ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen); return ImGui::TreeNodeEx(this->getDisplayName(pattern).c_str(), ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen);
} }
}); });
}
} }
void PatternDrawer::makeSelectable(const pl::ptrn::Pattern &pattern) { void PatternDrawer::makeSelectable(const pl::ptrn::Pattern &pattern) {
@ -389,43 +395,44 @@ namespace hex::plugin::builtin::ui {
ImGui::TextFormattedColored(ImColor(0xFF9BC64D), "bits"); ImGui::TextFormattedColored(ImColor(0xFF9BC64D), "bits");
ImGui::TableNextColumn(); ImGui::TableNextColumn();
if (this->isEditingPattern(pattern)) { if (!this->isEditingPattern(pattern)) {
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
auto value = pattern.getValue();
auto valueString = pattern.toString();
if (pattern.getBitSize() == 1) {
bool boolValue = value.toBoolean();
if (ImGui::Checkbox("##boolean", &boolValue)) {
pattern.setValue(boolValue);
}
} else if (std::holds_alternative<i128>(value)) {
if (ImGui::InputText("##Value", valueString, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) {
MathEvaluator<i128> mathEvaluator;
if (auto result = mathEvaluator.evaluate(valueString); result.has_value())
pattern.setValue(result.value());
this->resetEditing();
}
} else if (std::holds_alternative<u128>(value)) {
if (ImGui::InputText("##Value", valueString, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) {
MathEvaluator<u128> mathEvaluator;
if (auto result = mathEvaluator.evaluate(valueString); result.has_value())
pattern.setValue(result.value());
this->resetEditing();
}
}
ImGui::PopItemWidth();
ImGui::PopStyleVar();
} else {
drawValueColumn(pattern); drawValueColumn(pattern);
return;
} }
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
auto value = pattern.getValue();
auto valueString = pattern.toString();
if (pattern.getBitSize() == 1) {
bool boolValue = value.toBoolean();
if (ImGui::Checkbox("##boolean", &boolValue)) {
pattern.setValue(boolValue);
}
} else if (std::holds_alternative<i128>(value)) {
if (ImGui::InputText("##Value", valueString, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) {
MathEvaluator<i128> mathEvaluator;
if (auto result = mathEvaluator.evaluate(valueString); result.has_value())
pattern.setValue(result.value());
this->resetEditing();
}
} else if (std::holds_alternative<u128>(value)) {
if (ImGui::InputText("##Value", valueString, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) {
MathEvaluator<u128> mathEvaluator;
if (auto result = mathEvaluator.evaluate(valueString); result.has_value())
pattern.setValue(result.value());
this->resetEditing();
}
}
ImGui::PopItemWidth();
ImGui::PopStyleVar();
} }
void PatternDrawer::visit(pl::ptrn::PatternBitfieldArray& pattern) { void PatternDrawer::visit(pl::ptrn::PatternBitfieldArray& pattern) {
@ -455,60 +462,64 @@ namespace hex::plugin::builtin::ui {
drawValueColumn(pattern); drawValueColumn(pattern);
} }
if (open) { if (!open) {
int id = 1; return;
pattern.forEachEntry(0, pattern.getEntryCount(), [&] (u64, auto *field) {
ImGui::PushID(id);
this->draw(*field);
ImGui::PopID();
id += 1;
});
closeTreeNode(pattern.isInlined());
} }
int id = 1;
pattern.forEachEntry(0, pattern.getEntryCount(), [&] (u64, auto *field) {
ImGui::PushID(id);
this->draw(*field);
ImGui::PopID();
id += 1;
});
closeTreeNode(pattern.isInlined());
} }
void PatternDrawer::visit(pl::ptrn::PatternBoolean& pattern) { void PatternDrawer::visit(pl::ptrn::PatternBoolean& pattern) {
createDefaultEntry(pattern); createDefaultEntry(pattern);
if (this->isEditingPattern(pattern)) { if (!this->isEditingPattern(pattern)) {
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
bool value = pattern.getValue().toBoolean();
if (ImGui::Checkbox("##boolean", &value)) {
pattern.setValue(value);
}
ImGui::PopItemWidth();
ImGui::PopStyleVar();
} else {
drawValueColumn(pattern); drawValueColumn(pattern);
return;
} }
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
bool value = pattern.getValue().toBoolean();
if (ImGui::Checkbox("##boolean", &value)) {
pattern.setValue(value);
}
ImGui::PopItemWidth();
ImGui::PopStyleVar();
} }
void PatternDrawer::visit(pl::ptrn::PatternCharacter& pattern) { void PatternDrawer::visit(pl::ptrn::PatternCharacter& pattern) {
createDefaultEntry(pattern); createDefaultEntry(pattern);
if (this->isEditingPattern(pattern)) { if (!this->isEditingPattern(pattern)) {
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
auto value = hex::encodeByteString(pattern.getBytes());
if (ImGui::InputText("##Character", value.data(), value.size() + 1, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) {
if (!value.empty()) {
auto result = hex::decodeByteString(value);
if (!result.empty())
pattern.setValue(char(result[0]));
this->resetEditing();
}
}
ImGui::PopItemWidth();
ImGui::PopStyleVar();
} else {
drawValueColumn(pattern); drawValueColumn(pattern);
return;
} }
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
auto value = hex::encodeByteString(pattern.getBytes());
if (ImGui::InputText("##Character", value.data(), value.size() + 1, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) {
if (!value.empty()) {
auto result = hex::decodeByteString(value);
if (!result.empty())
pattern.setValue(char(result[0]));
this->resetEditing();
}
}
ImGui::PopItemWidth();
ImGui::PopStyleVar();
} }
void PatternDrawer::visit(pl::ptrn::PatternEnum& pattern) { void PatternDrawer::visit(pl::ptrn::PatternEnum& pattern) {
@ -524,56 +535,58 @@ namespace hex::plugin::builtin::ui {
drawSizeColumn(pattern); drawSizeColumn(pattern);
drawTypenameColumn(pattern, "enum"); drawTypenameColumn(pattern, "enum");
if (this->isEditingPattern(pattern)) { if (!this->isEditingPattern(pattern)) {
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
if (ImGui::BeginCombo("##Enum", pattern.getFormattedValue().c_str())) {
auto currValue = pattern.getValue().toUnsigned();
for (auto &value : pattern.getEnumValues()) {
auto min = value.min.toUnsigned();
auto max = value.max.toUnsigned();
bool isSelected = min <= currValue && max >= currValue;
if (ImGui::Selectable(fmt::format("{}::{} (0x{:0{}X})", pattern.getTypeName(), value.name, min, pattern.getSize() * 2).c_str(), isSelected)) {
pattern.setValue(value.min);
this->resetEditing();
}
if (isSelected)
ImGui::SetItemDefaultFocus();
}
ImGui::EndCombo();
}
ImGui::PopItemWidth();
ImGui::PopStyleVar();
} else {
drawValueColumn(pattern); drawValueColumn(pattern);
return;
} }
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
if (ImGui::BeginCombo("##Enum", pattern.getFormattedValue().c_str())) {
auto currValue = pattern.getValue().toUnsigned();
for (auto &value : pattern.getEnumValues()) {
auto min = value.min.toUnsigned();
auto max = value.max.toUnsigned();
bool isSelected = min <= currValue && max >= currValue;
if (ImGui::Selectable(fmt::format("{}::{} (0x{:0{}X})", pattern.getTypeName(), value.name, min, pattern.getSize() * 2).c_str(), isSelected)) {
pattern.setValue(value.min);
this->resetEditing();
}
if (isSelected)
ImGui::SetItemDefaultFocus();
}
ImGui::EndCombo();
}
ImGui::PopItemWidth();
ImGui::PopStyleVar();
} }
void PatternDrawer::visit(pl::ptrn::PatternFloat& pattern) { void PatternDrawer::visit(pl::ptrn::PatternFloat& pattern) {
createDefaultEntry(pattern); createDefaultEntry(pattern);
if (this->isEditingPattern(pattern)) { if (!this->isEditingPattern(pattern)) {
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
auto value = pattern.toString();
if (ImGui::InputText("##Value", value, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) {
MathEvaluator<long double> mathEvaluator;
if (auto result = mathEvaluator.evaluate(value); result.has_value())
pattern.setValue(double(result.value()));
this->resetEditing();
}
ImGui::PopItemWidth();
ImGui::PopStyleVar();
} else {
drawValueColumn(pattern); drawValueColumn(pattern);
return;
} }
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
auto value = pattern.toString();
if (ImGui::InputText("##Value", value, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) {
MathEvaluator<long double> mathEvaluator;
if (auto result = mathEvaluator.evaluate(value); result.has_value())
pattern.setValue(double(result.value()));
this->resetEditing();
}
ImGui::PopItemWidth();
ImGui::PopStyleVar();
} }
void PatternDrawer::visit(pl::ptrn::PatternPadding& pattern) { void PatternDrawer::visit(pl::ptrn::PatternPadding& pattern) {
@ -610,46 +623,48 @@ namespace hex::plugin::builtin::ui {
void PatternDrawer::visit(pl::ptrn::PatternSigned& pattern) { void PatternDrawer::visit(pl::ptrn::PatternSigned& pattern) {
createDefaultEntry(pattern); createDefaultEntry(pattern);
if (this->isEditingPattern(pattern)) { if (!this->isEditingPattern(pattern)) {
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
auto value = pattern.getFormattedValue();
if (ImGui::InputText("##Value", value, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) {
MathEvaluator<i128> mathEvaluator;
if (auto result = mathEvaluator.evaluate(value); result.has_value())
pattern.setValue(result.value());
this->resetEditing();
}
ImGui::PopItemWidth();
ImGui::PopStyleVar();
} else {
drawValueColumn(pattern); drawValueColumn(pattern);
return;
} }
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
auto value = pattern.getFormattedValue();
if (ImGui::InputText("##Value", value, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) {
MathEvaluator<i128> mathEvaluator;
if (auto result = mathEvaluator.evaluate(value); result.has_value())
pattern.setValue(result.value());
this->resetEditing();
}
ImGui::PopItemWidth();
ImGui::PopStyleVar();
} }
void PatternDrawer::visit(pl::ptrn::PatternString& pattern) { void PatternDrawer::visit(pl::ptrn::PatternString& pattern) {
if (pattern.getSize() > 0) { if (pattern.getSize() > 0) {
createDefaultEntry(pattern); createDefaultEntry(pattern);
if (this->isEditingPattern(pattern)) { if (!this->isEditingPattern(pattern)) {
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
auto value = pattern.toString();
if (ImGui::InputText("##Value", value.data(), value.size() + 1, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) {
pattern.setValue(value);
this->resetEditing();
}
ImGui::PopItemWidth();
ImGui::PopStyleVar();
} else {
drawValueColumn(pattern); drawValueColumn(pattern);
return;
} }
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
auto value = pattern.toString();
if (ImGui::InputText("##Value", value.data(), value.size() + 1, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) {
pattern.setValue(value);
this->resetEditing();
}
ImGui::PopItemWidth();
ImGui::PopStyleVar();
} }
} }
@ -688,17 +703,19 @@ namespace hex::plugin::builtin::ui {
} }
if (open) { if (!open) {
int id = 1; return;
pattern.forEachEntry(0, pattern.getEntryCount(), [&](u64, auto *member){
ImGui::PushID(id);
this->draw(*member);
ImGui::PopID();
id += 1;
});
closeTreeNode(pattern.isInlined());
} }
int id = 1;
pattern.forEachEntry(0, pattern.getEntryCount(), [&](u64, auto *member){
ImGui::PushID(id);
this->draw(*member);
ImGui::PopID();
id += 1;
});
closeTreeNode(pattern.isInlined());
} }
void PatternDrawer::visit(pl::ptrn::PatternUnion& pattern) { void PatternDrawer::visit(pl::ptrn::PatternUnion& pattern) {
@ -735,40 +752,43 @@ namespace hex::plugin::builtin::ui {
} }
} }
if (open) { if (!open) {
int id = 1; return;
pattern.forEachEntry(0, pattern.getEntryCount(), [&](u64, auto *member) {
ImGui::PushID(id);
this->draw(*member);
ImGui::PopID();
id += 1;
});
closeTreeNode(pattern.isInlined());
} }
int id = 1;
pattern.forEachEntry(0, pattern.getEntryCount(), [&](u64, auto *member) {
ImGui::PushID(id);
this->draw(*member);
ImGui::PopID();
id += 1;
});
closeTreeNode(pattern.isInlined());
} }
void PatternDrawer::visit(pl::ptrn::PatternUnsigned& pattern) { void PatternDrawer::visit(pl::ptrn::PatternUnsigned& pattern) {
createDefaultEntry(pattern); createDefaultEntry(pattern);
if (this->isEditingPattern(pattern)) { if (!this->isEditingPattern(pattern)) {
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
auto value = pattern.toString();
if (ImGui::InputText("##Value", value, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) {
MathEvaluator<u128> mathEvaluator;
if (auto result = mathEvaluator.evaluate(value); result.has_value())
pattern.setValue(result.value());
this->resetEditing();
}
ImGui::PopItemWidth();
ImGui::PopStyleVar();
} else {
drawValueColumn(pattern); drawValueColumn(pattern);
return;
} }
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
auto value = pattern.toString();
if (ImGui::InputText("##Value", value, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) {
MathEvaluator<u128> mathEvaluator;
if (auto result = mathEvaluator.evaluate(value); result.has_value())
pattern.setValue(result.value());
this->resetEditing();
}
ImGui::PopItemWidth();
ImGui::PopStyleVar();
} }
void PatternDrawer::visit(pl::ptrn::PatternWideCharacter& pattern) { void PatternDrawer::visit(pl::ptrn::PatternWideCharacter& pattern) {
@ -828,77 +848,81 @@ namespace hex::plugin::builtin::ui {
drawValueColumn(pattern); drawValueColumn(pattern);
} }
if (open) { if (!open) {
u64 chunkCount = 0; return;
for (u64 i = 0; i < iterable.getEntryCount(); i += ChunkSize) { }
chunkCount++;
auto &displayEnd = this->getDisplayEnd(pattern); u64 chunkCount = 0;
if (chunkCount > displayEnd) { for (u64 i = 0; i < iterable.getEntryCount(); i += ChunkSize) {
ImGui::TableNextRow(); chunkCount++;
ImGui::TableNextColumn();
ImGui::TableNextColumn();
ImGui::Selectable(hex::format("... ({})", "hex.builtin.pattern_drawer.double_click"_lang).c_str(), false, ImGuiSelectableFlags_SpanAllColumns); auto &displayEnd = this->getDisplayEnd(pattern);
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) if (chunkCount > displayEnd) {
displayEnd += DisplayEndStep; ImGui::TableNextRow();
break; ImGui::TableNextColumn();
} else { ImGui::TableNextColumn();
auto endIndex = std::min<u64>(iterable.getEntryCount(), i + ChunkSize);
bool chunkOpen = true; ImGui::Selectable(hex::format("... ({})", "hex.builtin.pattern_drawer.double_click"_lang).c_str(), false, ImGuiSelectableFlags_SpanAllColumns);
if (iterable.getEntryCount() > ChunkSize) { if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
auto startOffset = iterable.getEntry(i)->getOffset(); displayEnd += DisplayEndStep;
auto endOffset = iterable.getEntry(endIndex - 1)->getOffset(); break;
auto endSize = iterable.getEntry(endIndex - 1)->getSize();
size_t chunkSize = (endOffset - startOffset) + endSize;
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TableNextColumn();
chunkOpen = highlightWhenSelected(startOffset, ((endOffset + endSize) - startOffset) - 1, [&]{
return ImGui::TreeNodeEx(hex::format("{0}[{1} ... {2}]", this->m_treeStyle == TreeStyle::Flattened ? this->getDisplayName(pattern).c_str() : "", i, endIndex - 1).c_str(), ImGuiTreeNodeFlags_SpanFullWidth);
});
ImGui::TableNextColumn();
ImGui::TableNextColumn();
drawOffsetColumn(pattern);
ImGui::TextFormatted("0x{0:04X}", chunkSize);
ImGui::TableNextColumn();
ImGui::TextFormattedColored(ImColor(0xFF9BC64D), "{0}", pattern.getTypeName());
ImGui::SameLine(0, 0);
ImGui::TextUnformatted("[");
ImGui::SameLine(0, 0);
ImGui::TextFormattedColored(ImColor(0xFF00FF00), "{0}", endIndex - i);
ImGui::SameLine(0, 0);
ImGui::TextUnformatted("]");
ImGui::TableNextColumn();
ImGui::TextFormatted("[ ... ]");
}
if (chunkOpen) {
int id = 1;
iterable.forEachEntry(i, endIndex, [&](u64, auto *entry){
ImGui::PushID(id);
this->draw(*entry);
ImGui::PopID();
id += 1;
});
if (iterable.getEntryCount() > ChunkSize)
ImGui::TreePop();
}
}
} }
closeTreeNode(isInlined); auto endIndex = std::min<u64>(iterable.getEntryCount(), i + ChunkSize);
bool chunkOpen = true;
if (iterable.getEntryCount() > ChunkSize) {
auto startOffset = iterable.getEntry(i)->getOffset();
auto endOffset = iterable.getEntry(endIndex - 1)->getOffset();
auto endSize = iterable.getEntry(endIndex - 1)->getSize();
size_t chunkSize = (endOffset - startOffset) + endSize;
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TableNextColumn();
chunkOpen = highlightWhenSelected(startOffset, ((endOffset + endSize) - startOffset) - 1, [&]{
return ImGui::TreeNodeEx(hex::format("{0}[{1} ... {2}]", this->m_treeStyle == TreeStyle::Flattened ? this->getDisplayName(pattern).c_str() : "", i, endIndex - 1).c_str(), ImGuiTreeNodeFlags_SpanFullWidth);
});
ImGui::TableNextColumn();
ImGui::TableNextColumn();
drawOffsetColumn(pattern);
ImGui::TextFormatted("0x{0:04X}", chunkSize);
ImGui::TableNextColumn();
ImGui::TextFormattedColored(ImColor(0xFF9BC64D), "{0}", pattern.getTypeName());
ImGui::SameLine(0, 0);
ImGui::TextUnformatted("[");
ImGui::SameLine(0, 0);
ImGui::TextFormattedColored(ImColor(0xFF00FF00), "{0}", endIndex - i);
ImGui::SameLine(0, 0);
ImGui::TextUnformatted("]");
ImGui::TableNextColumn();
ImGui::TextFormatted("[ ... ]");
}
if (!chunkOpen) {
continue;
}
int id = 1;
iterable.forEachEntry(i, endIndex, [&](u64, auto *entry){
ImGui::PushID(id);
this->draw(*entry);
ImGui::PopID();
id += 1;
});
if (iterable.getEntryCount() > ChunkSize)
ImGui::TreePop();
} }
closeTreeNode(isInlined);
} }
u64& PatternDrawer::getDisplayEnd(const pl::ptrn::Pattern& pattern) { u64& PatternDrawer::getDisplayEnd(const pl::ptrn::Pattern& pattern) {
@ -953,44 +977,48 @@ namespace hex::plugin::builtin::ui {
} }
bool PatternDrawer::beginPatternTable(const std::vector<std::shared_ptr<pl::ptrn::Pattern>> &patterns, std::vector<pl::ptrn::Pattern*> &sortedPatterns, float height) { bool PatternDrawer::beginPatternTable(const std::vector<std::shared_ptr<pl::ptrn::Pattern>> &patterns, std::vector<pl::ptrn::Pattern*> &sortedPatterns, float height) {
if (ImGui::BeginTable("##Patterntable", 8, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Sortable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY, ImVec2(0, height))) { if (!ImGui::BeginTable("##Patterntable", 8, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Sortable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY, ImVec2(0, height))) {
ImGui::TableSetupScrollFreeze(0, 1); return false;
ImGui::TableSetupColumn("##favorite", ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_NoReorder | ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_IndentDisable, ImGui::GetTextLineHeight(), ImGui::GetID("favorite")); }
ImGui::TableSetupColumn("hex.builtin.pattern_drawer.var_name"_lang, ImGuiTableColumnFlags_PreferSortAscending | ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_IndentEnable, 0, ImGui::GetID("name"));
ImGui::TableSetupColumn("hex.builtin.pattern_drawer.color"_lang, ImGuiTableColumnFlags_PreferSortAscending, 0, ImGui::GetID("color")); ImGui::TableSetupScrollFreeze(0, 1);
ImGui::TableSetupColumn("hex.builtin.pattern_drawer.start"_lang, ImGuiTableColumnFlags_PreferSortAscending | ImGuiTableColumnFlags_DefaultSort, 0, ImGui::GetID("start")); ImGui::TableSetupColumn("##favorite", ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_NoReorder | ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_IndentDisable, ImGui::GetTextLineHeight(), ImGui::GetID("favorite"));
ImGui::TableSetupColumn("hex.builtin.pattern_drawer.end"_lang, ImGuiTableColumnFlags_PreferSortAscending | ImGuiTableColumnFlags_DefaultSort, 0, ImGui::GetID("end")); ImGui::TableSetupColumn("hex.builtin.pattern_drawer.var_name"_lang, ImGuiTableColumnFlags_PreferSortAscending | ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_IndentEnable, 0, ImGui::GetID("name"));
ImGui::TableSetupColumn("hex.builtin.pattern_drawer.size"_lang, ImGuiTableColumnFlags_PreferSortAscending, 0, ImGui::GetID("size")); ImGui::TableSetupColumn("hex.builtin.pattern_drawer.color"_lang, ImGuiTableColumnFlags_PreferSortAscending, 0, ImGui::GetID("color"));
ImGui::TableSetupColumn("hex.builtin.pattern_drawer.type"_lang, ImGuiTableColumnFlags_PreferSortAscending, 0, ImGui::GetID("type")); ImGui::TableSetupColumn("hex.builtin.pattern_drawer.start"_lang, ImGuiTableColumnFlags_PreferSortAscending | ImGuiTableColumnFlags_DefaultSort, 0, ImGui::GetID("start"));
ImGui::TableSetupColumn("hex.builtin.pattern_drawer.value"_lang, ImGuiTableColumnFlags_PreferSortAscending, 0, ImGui::GetID("value")); ImGui::TableSetupColumn("hex.builtin.pattern_drawer.end"_lang, ImGuiTableColumnFlags_PreferSortAscending | ImGuiTableColumnFlags_DefaultSort, 0, ImGui::GetID("end"));
ImGui::TableSetupColumn("hex.builtin.pattern_drawer.size"_lang, ImGuiTableColumnFlags_PreferSortAscending, 0, ImGui::GetID("size"));
ImGui::TableSetupColumn("hex.builtin.pattern_drawer.type"_lang, ImGuiTableColumnFlags_PreferSortAscending, 0, ImGui::GetID("type"));
ImGui::TableSetupColumn("hex.builtin.pattern_drawer.value"_lang, ImGuiTableColumnFlags_PreferSortAscending, 0, ImGui::GetID("value"));
auto sortSpecs = ImGui::TableGetSortSpecs(); auto sortSpecs = ImGui::TableGetSortSpecs();
if (patterns.empty())
sortedPatterns.clear();
if (!patterns.empty() && (sortSpecs->SpecsDirty || sortedPatterns.empty())) {
sortedPatterns.clear();
std::transform(patterns.begin(), patterns.end(), std::back_inserter(sortedPatterns), [](const std::shared_ptr<pl::ptrn::Pattern> &pattern) {
return pattern.get();
});
std::sort(sortedPatterns.begin(), sortedPatterns.end(), [this, &sortSpecs](pl::ptrn::Pattern *left, pl::ptrn::Pattern *right) -> bool {
return this->sortPatterns(sortSpecs, left, right);
});
for (auto &pattern : sortedPatterns)
pattern->sort([this, &sortSpecs](const pl::ptrn::Pattern *left, const pl::ptrn::Pattern *right){
return this->sortPatterns(sortSpecs, left, right);
});
sortSpecs->SpecsDirty = false;
}
if (patterns.empty()) {
sortedPatterns.clear();
return true; return true;
} }
return false; if (!sortSpecs->SpecsDirty && !sortedPatterns.empty()) {
return true;
}
sortedPatterns.clear();
std::transform(patterns.begin(), patterns.end(), std::back_inserter(sortedPatterns), [](const std::shared_ptr<pl::ptrn::Pattern> &pattern) {
return pattern.get();
});
std::sort(sortedPatterns.begin(), sortedPatterns.end(), [this, &sortSpecs](pl::ptrn::Pattern *left, pl::ptrn::Pattern *right) -> bool {
return this->sortPatterns(sortSpecs, left, right);
});
for (auto &pattern : sortedPatterns)
pattern->sort([this, &sortSpecs](const pl::ptrn::Pattern *left, const pl::ptrn::Pattern *right){
return this->sortPatterns(sortSpecs, left, right);
});
sortSpecs->SpecsDirty = false;
return true;
} }
void PatternDrawer::traversePatternTree(pl::ptrn::Pattern &pattern, std::vector<std::string> &patternPath, const std::function<void(pl::ptrn::Pattern&)> &callback) { void PatternDrawer::traversePatternTree(pl::ptrn::Pattern &pattern, std::vector<std::string> &patternPath, const std::function<void(pl::ptrn::Pattern&)> &callback) {