mirror of https://github.com/WerWolv/ImHex
feat: Add support for custom inspector edit widgets
This commit is contained in:
parent
21e61bfce6
commit
de25ce7fbb
|
|
@ -8,6 +8,7 @@
|
|||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <bit>
|
||||
|
||||
EXPORT_MODULE namespace hex {
|
||||
|
||||
|
|
@ -22,8 +23,10 @@ EXPORT_MODULE namespace hex {
|
|||
|
||||
namespace impl {
|
||||
|
||||
struct DoNotUseThisByItselfTag {};
|
||||
|
||||
using DisplayFunction = std::function<std::string()>;
|
||||
using EditingFunction = std::function<std::vector<u8>(std::string, std::endian)>;
|
||||
using EditingFunction = std::function<std::optional<std::vector<u8>>(std::string&, std::endian, DoNotUseThisByItselfTag)>;
|
||||
using GeneratorFunction = std::function<DisplayFunction(const std::vector<u8> &, std::endian, NumberDisplayStyle)>;
|
||||
|
||||
struct Entry {
|
||||
|
|
@ -38,6 +41,35 @@ EXPORT_MODULE namespace hex {
|
|||
|
||||
}
|
||||
|
||||
namespace EditWidget {
|
||||
|
||||
class Widget {
|
||||
public:
|
||||
using Function = std::function<std::vector<u8>(const std::string&, std::endian)>;
|
||||
|
||||
explicit Widget(const Function &function) : m_function(function) {}
|
||||
|
||||
virtual ~Widget() = default;
|
||||
virtual std::optional<std::vector<u8>> draw(std::string &value, std::endian endian) = 0;
|
||||
std::optional<std::vector<u8>> operator()(std::string &value, std::endian endian, impl::DoNotUseThisByItselfTag) {
|
||||
return draw(value, endian);
|
||||
}
|
||||
|
||||
std::vector<u8> getBytes(const std::string &value, std::endian endian) const {
|
||||
return m_function(value, endian);
|
||||
}
|
||||
|
||||
private:
|
||||
Function m_function;
|
||||
};
|
||||
|
||||
struct TextInput : Widget {
|
||||
explicit TextInput(const Function &function) : Widget(function) {}
|
||||
std::optional<std::vector<u8>> draw(std::string &value, std::endian endian) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a new entry to the data inspector
|
||||
* @param unlocalizedName The unlocalized name of the entry
|
||||
|
|
|
|||
|
|
@ -870,6 +870,18 @@ namespace hex {
|
|||
|
||||
}
|
||||
|
||||
namespace EditWidget {
|
||||
std::optional<std::vector<u8>> TextInput::draw(std::string &value, std::endian endian) {
|
||||
if (ImGui::InputText("##InspectorLineEditing", value,
|
||||
ImGuiInputTextFlags_EnterReturnsTrue |
|
||||
ImGuiInputTextFlags_AutoSelectAll)) {
|
||||
return getBytes(value, endian);
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
void add(const UnlocalizedString &unlocalizedName, size_t requiredSize, impl::GeneratorFunction displayGeneratorFunction, std::optional<impl::EditingFunction> editingFunction) {
|
||||
log::debug("Registered new data inspector format: {}", unlocalizedName.get());
|
||||
|
||||
|
|
|
|||
|
|
@ -33,54 +33,60 @@ namespace hex::plugin::builtin {
|
|||
};
|
||||
|
||||
template<std::unsigned_integral T, size_t Size = sizeof(T)>
|
||||
static std::vector<u8> stringToUnsigned(const std::string &value, std::endian endian) requires(sizeof(T) <= sizeof(u64)) {
|
||||
const auto result = wolv::util::from_chars<u64>(value).value_or(0);
|
||||
if (result > std::numeric_limits<T>::max()) return {};
|
||||
static ContentRegistry::DataInspector::impl::EditingFunction stringToUnsigned() requires(sizeof(T) <= sizeof(u64)) {
|
||||
return ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||
const auto result = wolv::util::from_chars<u64>(value).value_or(0);
|
||||
if (result > std::numeric_limits<T>::max()) return {};
|
||||
|
||||
std::vector<u8> bytes(Size, 0x00);
|
||||
std::memcpy(bytes.data(), &result, bytes.size());
|
||||
std::vector<u8> bytes(Size, 0x00);
|
||||
std::memcpy(bytes.data(), &result, bytes.size());
|
||||
|
||||
if (endian != std::endian::native)
|
||||
std::reverse(bytes.begin(), bytes.end());
|
||||
if (endian != std::endian::native)
|
||||
std::reverse(bytes.begin(), bytes.end());
|
||||
|
||||
return bytes;
|
||||
return bytes;
|
||||
});
|
||||
}
|
||||
|
||||
template<std::signed_integral T, size_t Size = sizeof(T)>
|
||||
static std::vector<u8> stringToSigned(const std::string &value, std::endian endian) requires(sizeof(T) <= sizeof(u64)) {
|
||||
const auto result = wolv::util::from_chars<i64>(value).value_or(0);
|
||||
if (result > std::numeric_limits<T>::max() || result < std::numeric_limits<T>::min()) return {};
|
||||
static ContentRegistry::DataInspector::impl::EditingFunction stringToSigned() requires(sizeof(T) <= sizeof(u64)) {
|
||||
return ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||
const auto result = wolv::util::from_chars<i64>(value).value_or(0);
|
||||
if (result > std::numeric_limits<T>::max() || result < std::numeric_limits<T>::min()) return {};
|
||||
|
||||
std::vector<u8> bytes(Size, 0x00);
|
||||
std::memcpy(bytes.data(), &result, bytes.size());
|
||||
std::vector<u8> bytes(Size, 0x00);
|
||||
std::memcpy(bytes.data(), &result, bytes.size());
|
||||
|
||||
if (endian != std::endian::native)
|
||||
std::reverse(bytes.begin(), bytes.end());
|
||||
if (endian != std::endian::native)
|
||||
std::reverse(bytes.begin(), bytes.end());
|
||||
|
||||
return bytes;
|
||||
return bytes;
|
||||
});
|
||||
}
|
||||
|
||||
template<std::floating_point T>
|
||||
static std::vector<u8> stringToFloat(const std::string &value, std::endian endian) requires(sizeof(T) <= sizeof(long double)) {
|
||||
const T result = wolv::util::from_chars<double>(value).value_or(0);
|
||||
static ContentRegistry::DataInspector::impl::EditingFunction stringToFloat() requires(sizeof(T) <= sizeof(long double)) {
|
||||
return ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||
const T result = wolv::util::from_chars<double>(value).value_or(0);
|
||||
|
||||
std::vector<u8> bytes(sizeof(T), 0x00);
|
||||
std::memcpy(bytes.data(), &result, bytes.size());
|
||||
std::vector<u8> bytes(sizeof(T), 0x00);
|
||||
std::memcpy(bytes.data(), &result, bytes.size());
|
||||
|
||||
if (endian != std::endian::native)
|
||||
std::reverse(bytes.begin(), bytes.end());
|
||||
if (endian != std::endian::native)
|
||||
std::reverse(bytes.begin(), bytes.end());
|
||||
|
||||
return bytes;
|
||||
return bytes;
|
||||
});
|
||||
}
|
||||
|
||||
template<std::integral T, size_t Size = sizeof(T)>
|
||||
static std::vector<u8> stringToInteger(const std::string &value, std::endian endian) requires(sizeof(T) <= sizeof(u64)) {
|
||||
static ContentRegistry::DataInspector::impl::EditingFunction stringToInteger() requires(sizeof(T) <= sizeof(u64)) {
|
||||
if constexpr (std::unsigned_integral<T>)
|
||||
return stringToUnsigned<T, Size>(value, endian);
|
||||
return stringToUnsigned<T, Size>();
|
||||
else if constexpr (std::signed_integral<T>)
|
||||
return stringToSigned<T, Size>(value, endian);
|
||||
return stringToSigned<T, Size>();
|
||||
else
|
||||
return {};
|
||||
static_assert("Unsupported type for stringToInteger");
|
||||
}
|
||||
|
||||
template<std::unsigned_integral T, size_t Size = sizeof(T)>
|
||||
|
|
@ -154,7 +160,8 @@ namespace hex::plugin::builtin {
|
|||
ImGui::TextUnformatted(binary.c_str());
|
||||
return binary;
|
||||
};
|
||||
}, [](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||
},
|
||||
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||
std::ignore = endian;
|
||||
|
||||
std::string binary = value;
|
||||
|
|
@ -167,69 +174,69 @@ namespace hex::plugin::builtin {
|
|||
return { result.value() };
|
||||
else
|
||||
return { };
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
|
||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.u8", sizeof(u8),
|
||||
drawString<u8>(integerToString<u8>),
|
||||
stringToInteger<u8>
|
||||
stringToInteger<u8>()
|
||||
);
|
||||
|
||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.i8", sizeof(i8),
|
||||
drawString<i8>(integerToString<i8>),
|
||||
stringToInteger<i8>
|
||||
stringToInteger<i8>()
|
||||
);
|
||||
|
||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.u16", sizeof(u16),
|
||||
drawString<u16>(integerToString<u16>),
|
||||
stringToInteger<u16>
|
||||
stringToInteger<u16>()
|
||||
);
|
||||
|
||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.i16", sizeof(i16),
|
||||
drawString<i16>(integerToString<i16>),
|
||||
stringToInteger<i16>
|
||||
stringToInteger<i16>()
|
||||
);
|
||||
|
||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.u24", 3,
|
||||
drawString<u32, 3>(integerToString<u32, 3>),
|
||||
stringToInteger<u32, 3>
|
||||
stringToInteger<u32, 3>()
|
||||
);
|
||||
|
||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.i24", 3,
|
||||
drawString<i32, 3>(integerToString<i32, 3>),
|
||||
stringToInteger<i32, 3>
|
||||
stringToInteger<i32, 3>()
|
||||
);
|
||||
|
||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.u32", sizeof(u32),
|
||||
drawString<u32>(integerToString<u32>),
|
||||
stringToInteger<u32>
|
||||
stringToInteger<u32>()
|
||||
);
|
||||
|
||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.i32", sizeof(i32),
|
||||
drawString<i32>(integerToString<i32>),
|
||||
stringToInteger<i32>
|
||||
stringToInteger<i32>()
|
||||
);
|
||||
|
||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.u48", 6,
|
||||
drawString<u64, 6>(integerToString<u64, 6>),
|
||||
stringToInteger<u64, 6>
|
||||
stringToInteger<u64, 6>()
|
||||
);
|
||||
|
||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.i48", 6,
|
||||
drawString<i64, 6>(integerToString<i64, 6>),
|
||||
stringToInteger<i64, 6>
|
||||
stringToInteger<i64, 6>()
|
||||
);
|
||||
|
||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.u64", sizeof(u64),
|
||||
drawString<u64>(integerToString<u64>),
|
||||
stringToInteger<u64>
|
||||
stringToInteger<u64>()
|
||||
);
|
||||
|
||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.i64", sizeof(i64),
|
||||
drawString<i64>(integerToString<i64>),
|
||||
stringToInteger<i64>
|
||||
stringToInteger<i64>()
|
||||
);
|
||||
|
||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.float16", sizeof(u16),
|
||||
|
|
@ -255,7 +262,7 @@ namespace hex::plugin::builtin {
|
|||
auto value = fmt::format(fmt::runtime(formatString), hex::changeEndianness(result, endian));
|
||||
return [value] { ImGui::TextUnformatted(value.c_str()); return value; };
|
||||
},
|
||||
stringToFloat<float>
|
||||
stringToFloat<float>()
|
||||
);
|
||||
|
||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.double", sizeof(double),
|
||||
|
|
@ -268,7 +275,7 @@ namespace hex::plugin::builtin {
|
|||
auto value = fmt::format(fmt::runtime(formatString), hex::changeEndianness(result, endian));
|
||||
return [value] { ImGui::TextUnformatted(value.c_str()); return value; };
|
||||
},
|
||||
stringToFloat<double>
|
||||
stringToFloat<double>()
|
||||
);
|
||||
|
||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.long_double", sizeof(long double),
|
||||
|
|
@ -281,7 +288,7 @@ namespace hex::plugin::builtin {
|
|||
auto value = fmt::format(fmt::runtime(formatString), hex::changeEndianness(result, endian));
|
||||
return [value] { ImGui::TextUnformatted(value.c_str()); return value; };
|
||||
},
|
||||
stringToFloat<long double>
|
||||
stringToFloat<long double>()
|
||||
);
|
||||
|
||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.bfloat16", sizeof(u16),
|
||||
|
|
@ -359,11 +366,11 @@ namespace hex::plugin::builtin {
|
|||
|
||||
return [value] { ImGui::TextUnformatted(value.c_str()); return value; };
|
||||
},
|
||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||
std::ignore = endian;
|
||||
|
||||
return hex::crypt::encodeSleb128(wolv::util::from_chars<i64>(value).value_or(0));
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.uleb128", 1, (sizeof(u128) * 8 / 7) + 1,
|
||||
|
|
@ -376,11 +383,11 @@ namespace hex::plugin::builtin {
|
|||
|
||||
return [value] { ImGui::TextUnformatted(value.c_str()); return value; };
|
||||
},
|
||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||
std::ignore = endian;
|
||||
|
||||
return hex::crypt::encodeUleb128(wolv::util::from_chars<u64>(value).value_or(0));
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.bool", sizeof(bool),
|
||||
|
|
@ -411,13 +418,13 @@ namespace hex::plugin::builtin {
|
|||
auto value = makePrintable(*reinterpret_cast<char8_t *>(buffer.data()));
|
||||
return [value] { ImGuiExt::TextFormatted("'{0}'", value.c_str()); return value; };
|
||||
},
|
||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||
std::ignore = endian;
|
||||
|
||||
if (value.length() > 1) return { };
|
||||
|
||||
return { u8(value[0]) };
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.wide", sizeof(wchar_t),
|
||||
|
|
@ -432,7 +439,7 @@ namespace hex::plugin::builtin {
|
|||
auto value = fmt::format("{0}", c <= 255 ? makePrintable(c) : wolv::util::wstringToUtf8(std::wstring(&c, 1)).value_or("???"));
|
||||
return [value] { ImGuiExt::TextFormatted("L'{0}'", value.c_str()); return value; };
|
||||
},
|
||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||
std::vector<u8> bytes;
|
||||
auto wideString = wolv::util::utf8ToWstring(value);
|
||||
if (!wideString.has_value())
|
||||
|
|
@ -445,7 +452,7 @@ namespace hex::plugin::builtin {
|
|||
std::reverse(bytes.begin(), bytes.end());
|
||||
|
||||
return bytes;
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.char16", sizeof(char16_t),
|
||||
|
|
@ -460,7 +467,7 @@ namespace hex::plugin::builtin {
|
|||
auto value = fmt::format("{0}", c <= 255 ? makePrintable(c) : wolv::util::utf16ToUtf8(std::u16string(&c, 1)).value_or("???"));
|
||||
return [value] { ImGuiExt::TextFormatted("u'{0}'", value.c_str()); return value; };
|
||||
},
|
||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||
std::vector<u8> bytes;
|
||||
auto wideString = wolv::util::utf8ToUtf16(value);
|
||||
if (!wideString.has_value())
|
||||
|
|
@ -473,7 +480,7 @@ namespace hex::plugin::builtin {
|
|||
std::reverse(bytes.begin(), bytes.end());
|
||||
|
||||
return bytes;
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.char32", sizeof(char32_t),
|
||||
|
|
@ -488,7 +495,7 @@ namespace hex::plugin::builtin {
|
|||
auto value = fmt::format("{0}", c <= 255 ? makePrintable(c) : wolv::util::utf32ToUtf8(std::u32string(&c, 1)).value_or("???"));
|
||||
return [value] { ImGuiExt::TextFormatted("U'{0}'", value.c_str()); return value; };
|
||||
},
|
||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||
std::vector<u8> bytes;
|
||||
auto wideString = wolv::util::utf8ToUtf32(value);
|
||||
if (!wideString.has_value())
|
||||
|
|
@ -501,7 +508,7 @@ namespace hex::plugin::builtin {
|
|||
std::reverse(bytes.begin(), bytes.end());
|
||||
|
||||
return bytes;
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.utf8", sizeof(char8_t) * 4,
|
||||
|
|
@ -551,11 +558,11 @@ namespace hex::plugin::builtin {
|
|||
|
||||
return [value, copyValue] { ImGuiExt::TextFormatted("\"{0}\"", value.c_str()); return copyValue; };
|
||||
},
|
||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||
std::ignore = endian;
|
||||
|
||||
return hex::decodeByteString(value);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.wstring", sizeof(wchar_t),
|
||||
|
|
@ -588,7 +595,7 @@ namespace hex::plugin::builtin {
|
|||
|
||||
return [value, copyValue] { ImGuiExt::TextFormatted("L\"{0}\"", value.c_str()); return copyValue; };
|
||||
},
|
||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||
auto utf8 = hex::decodeByteString(value);
|
||||
auto wstring = wolv::util::utf8ToWstring({ utf8.begin(), utf8.end() });
|
||||
if (!wstring.has_value())
|
||||
|
|
@ -601,7 +608,7 @@ namespace hex::plugin::builtin {
|
|||
std::vector<u8> bytes(wstring->size() * sizeof(wchar_t), 0x00);
|
||||
std::memcpy(bytes.data(), wstring->data(), bytes.size());
|
||||
return bytes;
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.string16", sizeof(char16_t),
|
||||
|
|
@ -634,7 +641,7 @@ namespace hex::plugin::builtin {
|
|||
|
||||
return [value, copyValue] { ImGuiExt::TextFormatted("u\"{0}\"", value.c_str()); return copyValue; };
|
||||
},
|
||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||
auto utf8 = hex::decodeByteString(value);
|
||||
auto utf16 = wolv::util::utf8ToUtf16({ utf8.begin(), utf8.end() });
|
||||
if (!utf16.has_value())
|
||||
|
|
@ -647,7 +654,7 @@ namespace hex::plugin::builtin {
|
|||
std::vector<u8> bytes(utf16->size() * sizeof(char16_t), 0x00);
|
||||
std::memcpy(bytes.data(), utf16->data(), bytes.size());
|
||||
return bytes;
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.string32", sizeof(char32_t),
|
||||
|
|
@ -680,7 +687,7 @@ namespace hex::plugin::builtin {
|
|||
|
||||
return [value, copyValue] { ImGuiExt::TextFormatted("U\"{0}\"", value.c_str()); return copyValue; };
|
||||
},
|
||||
[](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||
ContentRegistry::DataInspector::EditWidget::TextInput([](const std::string &value, std::endian endian) -> std::vector<u8> {
|
||||
auto utf8 = hex::decodeByteString(value);
|
||||
auto utf32 = wolv::util::utf8ToUtf32({ utf8.begin(), utf8.end() });
|
||||
if (!utf32.has_value())
|
||||
|
|
@ -693,7 +700,7 @@ namespace hex::plugin::builtin {
|
|||
std::vector<u8> bytes(utf32->size() * sizeof(char32_t), 0x00);
|
||||
std::memcpy(bytes.data(), utf32->data(), bytes.size());
|
||||
return bytes;
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
ContentRegistry::DataInspector::add("hex.builtin.inspector.custom_encoding", 1, [encodingFile = EncodingFile()](const std::vector<u8> &, std::endian, Style) mutable {
|
||||
|
|
|
|||
|
|
@ -198,8 +198,7 @@ namespace hex::plugin::builtin {
|
|||
// Set up the editing function if a write formatter is available
|
||||
std::optional<ContentRegistry::DataInspector::impl::EditingFunction> editingFunction;
|
||||
if (!pattern->getWriteFormatterFunction().empty()) {
|
||||
editingFunction = [&pattern](const std::string &value,
|
||||
std::endian) -> std::vector<u8> {
|
||||
editingFunction = ContentRegistry::DataInspector::EditWidget::TextInput([&pattern](const std::string &value, std::endian) -> std::vector<u8> {
|
||||
try {
|
||||
pattern->setValue(value);
|
||||
} catch (const pl::core::err::EvaluatorError::Exception &error) {
|
||||
|
|
@ -208,7 +207,7 @@ namespace hex::plugin::builtin {
|
|||
}
|
||||
|
||||
return {};
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
@ -441,7 +440,7 @@ namespace hex::plugin::builtin {
|
|||
ImGui::SameLine();
|
||||
|
||||
// Handle copying the value to the clipboard when clicking the row
|
||||
if (ImGui::Selectable("##InspectorLine", m_selectedEntryName == entry.unlocalizedName, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap)) {
|
||||
if (ImGui::Selectable("##InspectorLine", m_selectedEntryName == entry.unlocalizedName, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap | ImGuiSelectableFlags_AllowDoubleClick)) {
|
||||
m_selectedEntryName = entry.unlocalizedName;
|
||||
if (auto selection = ImHexApi::HexEditor::getSelection(); selection.has_value()) {
|
||||
ImHexApi::HexEditor::setSelection(Region { selection->getStartAddress(), entry.requiredSize });
|
||||
|
|
@ -476,47 +475,42 @@ namespace hex::plugin::builtin {
|
|||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
} else {
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_Escape)) {
|
||||
entry.editing = false;
|
||||
}
|
||||
|
||||
return;
|
||||
// Handle editing mode
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
ImGui::SetNextItemWidth(-1);
|
||||
ImGui::SetKeyboardFocusHere();
|
||||
|
||||
// Draw editing widget and capture edited value
|
||||
auto bytes = (*entry.editingFunction)(m_editingValue, m_endian, {});
|
||||
if (bytes.has_value()) {
|
||||
if (m_invert)
|
||||
std::ranges::transform(*bytes, bytes->begin(), [](auto byte) { return byte ^ 0xFF; });
|
||||
|
||||
// Write those bytes to the selected provider at the current address
|
||||
m_selectedProvider->write(m_startAddress, bytes->data(), bytes->size());
|
||||
|
||||
// Disable editing mode
|
||||
m_editingValue.clear();
|
||||
entry.editing = false;
|
||||
|
||||
// Reload all inspector rows
|
||||
m_shouldInvalidate = true;
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
// Disable editing mode when clicking outside the input text box
|
||||
if (!ImGui::IsItemHovered() && ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
|
||||
m_editingValue.clear();
|
||||
entry.editing = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_Escape)) {
|
||||
entry.editing = false;
|
||||
}
|
||||
|
||||
// Handle editing mode
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
ImGui::SetNextItemWidth(-1);
|
||||
ImGui::SetKeyboardFocusHere();
|
||||
|
||||
// Draw input text box
|
||||
if (ImGui::InputText("##InspectorLineEditing", m_editingValue,
|
||||
ImGuiInputTextFlags_EnterReturnsTrue |
|
||||
ImGuiInputTextFlags_AutoSelectAll)) {
|
||||
// Turn the entered value into bytes
|
||||
auto bytes = entry.editingFunction.value()(m_editingValue, m_endian);
|
||||
|
||||
if (m_invert)
|
||||
std::ranges::transform(bytes, bytes.begin(), [](auto byte) { return byte ^ 0xFF; });
|
||||
|
||||
// Write those bytes to the selected provider at the current address
|
||||
m_selectedProvider->write(m_startAddress, bytes.data(), bytes.size());
|
||||
|
||||
// Disable editing mode
|
||||
m_editingValue.clear();
|
||||
entry.editing = false;
|
||||
|
||||
// Reload all inspector rows
|
||||
m_shouldInvalidate = true;
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
// Disable editing mode when clicking outside the input text box
|
||||
if (!ImGui::IsItemHovered() && ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
|
||||
m_editingValue.clear();
|
||||
entry.editing = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ViewDataInspector::drawEndianSetting() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue