diff --git a/lib/libimhex/include/hex/providers/provider_data.hpp b/lib/libimhex/include/hex/providers/provider_data.hpp index 0fa0db5f9..f645843d6 100644 --- a/lib/libimhex/include/hex/providers/provider_data.hpp +++ b/lib/libimhex/include/hex/providers/provider_data.hpp @@ -38,7 +38,7 @@ namespace hex { } const T& get(prv::Provider *provider = ImHexApi::Provider::get()) const { - return m_data[provider]; + return m_data.at(provider); } void set(const T &data, prv::Provider *provider = ImHexApi::Provider::get()) { diff --git a/plugins/builtin/include/content/views/view_hex_editor.hpp b/plugins/builtin/include/content/views/view_hex_editor.hpp index 160592058..46735db9c 100644 --- a/plugins/builtin/include/content/views/view_hex_editor.hpp +++ b/plugins/builtin/include/content/views/view_hex_editor.hpp @@ -74,7 +74,6 @@ namespace hex::plugin::builtin { std::unique_ptr m_currPopup; PerProvider> m_selectionStart, m_selectionEnd; - PerProvider m_scrollPosition; PerProvider> m_foregroundHighlights, m_backgroundHighlights; }; diff --git a/plugins/builtin/source/content/views/view_hex_editor.cpp b/plugins/builtin/source/content/views/view_hex_editor.cpp index 67518fb8c..d6e75d5be 100644 --- a/plugins/builtin/source/content/views/view_hex_editor.cpp +++ b/plugins/builtin/source/content/views/view_hex_editor.cpp @@ -987,21 +987,15 @@ namespace hex::plugin::builtin { if (selection != Region::Invalid()) { m_selectionStart.get(oldProvider) = selection.getStartAddress(); m_selectionEnd.get(oldProvider) = selection.getEndAddress(); - m_scrollPosition.get(oldProvider) = m_hexEditor.getScrollPosition(); } } - m_hexEditor.setSelectionUnchecked(std::nullopt, std::nullopt); - m_hexEditor.setScrollPosition(0); - if (newProvider != nullptr) { m_hexEditor.setSelectionUnchecked(m_selectionStart.get(newProvider), m_selectionEnd.get(newProvider)); - m_hexEditor.setScrollPosition(m_scrollPosition.get(newProvider)); } else { ImHexApi::HexEditor::clearSelection(); } - m_hexEditor.forceUpdateScrollPosition(); if (isSelectionValid()) { EventRegionSelected::post(ImHexApi::HexEditor::ProviderRegion{ this->getSelection(), newProvider }); } diff --git a/plugins/ui/include/ui/hex_editor.hpp b/plugins/ui/include/ui/hex_editor.hpp index 3b74af62d..a27c50ea1 100644 --- a/plugins/ui/include/ui/hex_editor.hpp +++ b/plugins/ui/include/ui/hex_editor.hpp @@ -11,6 +11,65 @@ namespace hex::ui { + class ScrollPosition { + public: + ScrollPosition() = default; + + // We explicitly don't assign any data during copy and move operations so that each instance of the + // Hex Editor will get its own independent scroll position + ScrollPosition(const ScrollPosition&) { } + ScrollPosition(ScrollPosition&&) noexcept { } + ScrollPosition& operator=(const ScrollPosition&) { return *this; } + ScrollPosition& operator=(ScrollPosition&&) noexcept { return *this; } + + + void setSynced(bool synced) { + m_synced = synced; + } + + void setProvider(prv::Provider *provider) { + m_provider = provider; + } + + ImS64& get() { + if (m_synced) + return m_syncedPosition; + else + return m_unsyncedPosition.get(m_provider); + } + + const ImS64& get() const { + if (m_synced) + return m_syncedPosition; + else + return m_unsyncedPosition.get(m_provider); + } + + operator ImS64&() { + return this->get(); + } + + operator const ImS64&() const { + return this->get(); + } + + ScrollPosition& operator=(ImS64 value) { + this->get() = value; + return *this; + } + + auto operator<=>(const ScrollPosition &other) const { + return this->get() <=> other.get(); + } + + private: + bool m_synced = false; + prv::Provider *m_provider = nullptr; + + ImS64 m_syncedPosition = 0; + PerProvider m_unsyncedPosition; + }; + class HexEditor { public: explicit HexEditor(prv::Provider *provider = nullptr); @@ -20,6 +79,7 @@ namespace hex::ui { void setProvider(prv::Provider *provider) { m_provider = provider; m_currValidRegion = { Region::Invalid(), false }; + m_scrollPosition.setProvider(provider); } void setUnknownDataCharacter(char character) { m_unknownDataCharacter = character; } private: @@ -161,7 +221,7 @@ namespace hex::ui { } void enableSyncScrolling(bool syncScrolling) { - m_syncScrolling = syncScrolling; + m_scrollPosition.setSynced(syncScrolling); } void setByteCellPadding(u32 byteCellPadding) { @@ -202,12 +262,12 @@ namespace hex::ui { m_tooltipCallback = callback; } - [[nodiscard]] float getScrollPosition() const { - return m_scrollPosition; + [[nodiscard]] i64 getScrollPosition() const { + return m_scrollPosition.get(); } - void setScrollPosition(float scrollPosition) { - m_scrollPosition = scrollPosition; + void setScrollPosition(i64 scrollPosition) { + m_scrollPosition.get() = scrollPosition; } void setEditingAddress(u64 address) { @@ -230,7 +290,7 @@ namespace hex::ui { std::optional m_selectionStart; std::optional m_selectionEnd; std::optional m_cursorPosition; - ImS64 m_scrollPosition = 0; + ScrollPosition m_scrollPosition; u16 m_bytesPerRow = 16; std::endian m_dataVisualizerEndianness = std::endian::little; @@ -260,7 +320,6 @@ namespace hex::ui { bool m_showAscii = true; bool m_showCustomEncoding = true; bool m_showHumanReadableUnits = true; - bool m_syncScrolling = false; u32 m_byteCellPadding = 0, m_characterCellPadding = 0; bool m_footerCollapsed = true; diff --git a/plugins/ui/source/ui/hex_editor.cpp b/plugins/ui/source/ui/hex_editor.cpp index e629dec0e..6ab93c777 100644 --- a/plugins/ui/source/ui/hex_editor.cpp +++ b/plugins/ui/source/ui/hex_editor.cpp @@ -325,7 +325,7 @@ namespace hex::ui { bb, ImGui::GetWindowScrollbarID(window, axis), axis, - &m_scrollPosition, + &m_scrollPosition.get(), (std::ceil(innerRect.Max.y - innerRect.Min.y) / CharacterSize.y) - (m_visibleRowCount - 1), std::nextafterf(numRows, std::numeric_limits::max()), roundingCorners);