mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-04-02 05:27:41 -05:00
feat: Implement better and more complete undo/redo stack (#1433)
This PR aims to implement a more complete undo/redo stack that, unlike the old one, also supports undoing insertions, deletions and resize operations
This commit is contained in:
@@ -57,7 +57,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
[[nodiscard]] ImVec2 getMaxSize() const override {
|
||||
return scaled({ 600, 300 });
|
||||
return scaled({ 600, 600 });
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -20,12 +20,9 @@ namespace hex::plugin::builtin {
|
||||
[[nodiscard]] bool isResizable() const override;
|
||||
[[nodiscard]] bool isSavable() const override;
|
||||
|
||||
void read(u64 offset, void *buffer, size_t size, bool overlays) override;
|
||||
void write(u64 offset, const void *buffer, size_t size) override;
|
||||
|
||||
void resize(size_t newSize) override;
|
||||
void insert(u64 offset, size_t size) override;
|
||||
void remove(u64 offset, size_t size) override;
|
||||
void resizeRaw(size_t newSize) override;
|
||||
void insertRaw(u64 offset, size_t size) override;
|
||||
void removeRaw(u64 offset, size_t size) override;
|
||||
|
||||
void readRaw(u64 offset, void *buffer, size_t size) override;
|
||||
void writeRaw(u64 offset, const void *buffer, size_t size) override;
|
||||
|
||||
@@ -24,9 +24,9 @@ namespace hex::plugin::builtin {
|
||||
void writeRaw(u64 offset, const void *buffer, size_t size) override;
|
||||
[[nodiscard]] size_t getActualSize() const override { return this->m_data.size(); }
|
||||
|
||||
void resize(size_t newSize) override;
|
||||
void insert(u64 offset, size_t size) override;
|
||||
void remove(u64 offset, size_t size) override;
|
||||
void resizeRaw(size_t newSize) override;
|
||||
void insertRaw(u64 offset, size_t size) override;
|
||||
void removeRaw(u64 offset, size_t size) override;
|
||||
|
||||
void save() override;
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/providers/undo_redo/operations/operation.hpp>
|
||||
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
|
||||
namespace hex::plugin::builtin::undo {
|
||||
|
||||
class OperationBookmark : public prv::undo::Operation {
|
||||
public:
|
||||
explicit OperationBookmark(ImHexApi::Bookmarks::Entry entry) :
|
||||
m_entry(std::move(entry)) { }
|
||||
|
||||
void undo(prv::Provider *provider) override {
|
||||
hex::unused(provider);
|
||||
|
||||
ImHexApi::Bookmarks::remove(this->m_entry.id);
|
||||
}
|
||||
|
||||
void redo(prv::Provider *provider) override {
|
||||
hex::unused(provider);
|
||||
|
||||
auto &[region, name, comment, color, locked, id] = this->m_entry;
|
||||
|
||||
id = ImHexApi::Bookmarks::add(region, name, comment, color);
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string format() const override {
|
||||
return hex::format("Bookmark {} created", this->m_entry.name);
|
||||
}
|
||||
|
||||
std::unique_ptr<Operation> clone() const override {
|
||||
return std::make_unique<OperationBookmark>(*this);
|
||||
}
|
||||
|
||||
[[nodiscard]] Region getRegion() const override {
|
||||
return this->m_entry.region;
|
||||
}
|
||||
|
||||
bool shouldHighlight() const override { return false; }
|
||||
|
||||
private:
|
||||
ImHexApi::Bookmarks::Entry m_entry;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/providers/undo_redo/operations/operation.hpp>
|
||||
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
|
||||
namespace hex::plugin::builtin::undo {
|
||||
|
||||
class OperationInsert : public prv::undo::Operation {
|
||||
public:
|
||||
OperationInsert(u64 offset, u64 size) :
|
||||
m_offset(offset), m_size(size) { }
|
||||
|
||||
void undo(prv::Provider *provider) override {
|
||||
provider->removeRaw(this->m_offset, this->m_size);
|
||||
}
|
||||
|
||||
void redo(prv::Provider *provider) override {
|
||||
provider->insertRaw(this->m_offset, this->m_size);
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string format() const override {
|
||||
return hex::format("hex.builtin.undo_operation.insert"_lang, hex::toByteString(this->m_size), this->m_offset);
|
||||
}
|
||||
|
||||
std::unique_ptr<Operation> clone() const override {
|
||||
return std::make_unique<OperationInsert>(*this);
|
||||
}
|
||||
|
||||
[[nodiscard]] Region getRegion() const override {
|
||||
return { this->m_offset, this->m_size };
|
||||
}
|
||||
|
||||
private:
|
||||
u64 m_offset;
|
||||
u64 m_size;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/providers/undo_redo/operations/operation.hpp>
|
||||
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
|
||||
namespace hex::plugin::builtin::undo {
|
||||
|
||||
class OperationRemove : public prv::undo::Operation {
|
||||
public:
|
||||
OperationRemove(u64 offset, u64 size) :
|
||||
m_offset(offset), m_size(size) { }
|
||||
|
||||
void undo(prv::Provider *provider) override {
|
||||
provider->insertRaw(this->m_offset, this->m_size);
|
||||
|
||||
provider->writeRaw(this->m_offset, this->m_removedData.data(), this->m_removedData.size());
|
||||
}
|
||||
|
||||
void redo(prv::Provider *provider) override {
|
||||
this->m_removedData.resize(this->m_size);
|
||||
provider->readRaw(this->m_offset, this->m_removedData.data(), this->m_removedData.size());
|
||||
|
||||
provider->removeRaw(this->m_offset, this->m_size);
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string format() const override {
|
||||
return hex::format("hex.builtin.undo_operation.remove"_lang, hex::toByteString(this->m_size), this->m_offset);
|
||||
}
|
||||
|
||||
std::unique_ptr<Operation> clone() const override {
|
||||
return std::make_unique<OperationRemove>(*this);
|
||||
}
|
||||
|
||||
[[nodiscard]] Region getRegion() const override {
|
||||
return { this->m_offset, this->m_size };
|
||||
}
|
||||
|
||||
bool shouldHighlight() const override { return false; }
|
||||
|
||||
private:
|
||||
u64 m_offset;
|
||||
u64 m_size;
|
||||
std::vector<u8> m_removedData;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/helpers/crypto.hpp>
|
||||
#include <hex/providers/undo_redo/operations/operation.hpp>
|
||||
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
|
||||
namespace hex::plugin::builtin::undo {
|
||||
|
||||
class OperationWrite : public prv::undo::Operation {
|
||||
public:
|
||||
OperationWrite(u64 offset, u64 size, const u8 *oldData, const u8 *newData) :
|
||||
m_offset(offset),
|
||||
m_oldData(oldData, oldData + size),
|
||||
m_newData(newData, newData + size) { }
|
||||
|
||||
void undo(prv::Provider *provider) override {
|
||||
provider->writeRaw(this->m_offset, this->m_oldData.data(), this->m_oldData.size());
|
||||
}
|
||||
|
||||
void redo(prv::Provider *provider) override {
|
||||
provider->writeRaw(this->m_offset, this->m_newData.data(), this->m_newData.size());
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string format() const override {
|
||||
return hex::format("hex.builtin.undo_operation.write"_lang, hex::toByteString(this->m_newData.size()), this->m_offset);
|
||||
}
|
||||
|
||||
std::vector<std::string> formatContent() const override {
|
||||
return {
|
||||
hex::format("{} {} {}", hex::crypt::encode16(this->m_oldData), ICON_VS_ARROW_RIGHT, hex::crypt::encode16(this->m_newData)),
|
||||
};
|
||||
}
|
||||
|
||||
std::unique_ptr<Operation> clone() const override {
|
||||
return std::make_unique<OperationWrite>(*this);
|
||||
}
|
||||
|
||||
[[nodiscard]] Region getRegion() const override {
|
||||
return { this->m_offset, this->m_oldData.size() };
|
||||
}
|
||||
|
||||
private:
|
||||
u64 m_offset;
|
||||
std::vector<u8> m_oldData, m_newData;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -53,10 +53,10 @@ namespace hex::plugin::builtin {
|
||||
[[nodiscard]] bool open() override { return true; }
|
||||
void close() override { }
|
||||
|
||||
void resize(size_t newSize) override {
|
||||
void resizeRaw(size_t newSize) override {
|
||||
this->m_size = newSize;
|
||||
}
|
||||
void insert(u64 offset, size_t size) override {
|
||||
void insertRaw(u64 offset, size_t size) override {
|
||||
if (this->m_provider == nullptr)
|
||||
return;
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace hex::plugin::builtin {
|
||||
this->m_provider->insert(offset + this->m_startAddress, size);
|
||||
}
|
||||
|
||||
void remove(u64 offset, size_t size) override {
|
||||
void removeRaw(u64 offset, size_t size) override {
|
||||
if (this->m_provider == nullptr)
|
||||
return;
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
std::list<ImHexApi::Bookmarks::Entry>::iterator m_dragStartIterator;
|
||||
PerProvider<std::list<ImHexApi::Bookmarks::Entry>> m_bookmarks;
|
||||
PerProvider<u64> m_currBookmarkId;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -16,7 +16,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
private:
|
||||
u64 m_selectedPatch = 0x00;
|
||||
PerProvider<u32> m_numPatches;
|
||||
PerProvider<u32> m_numOperations;
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user