mirror of
https://github.com/MeowLynxSea/ceditor.git
synced 2025-07-09 10:54:37 +00:00
新增了ActionManager类,用于管理撤回、重做
This commit is contained in:
parent
b20d8aa6d0
commit
00b7386cfb
@ -211,6 +211,24 @@ public:
|
|||||||
long long operator-(iterator other) const {
|
long long operator-(iterator other) const {
|
||||||
return ptr - other.ptr;
|
return ptr - other.ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iterator& operator+=(size_t n) {
|
||||||
|
ptr += n;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
iterator& operator-=(size_t n) {
|
||||||
|
ptr -= n;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend iterator operator++(iterator& ite) {
|
||||||
|
++ite.ptr;
|
||||||
|
return ite;
|
||||||
|
}
|
||||||
|
friend iterator operator--(iterator& ite) {
|
||||||
|
--ite.ptr;
|
||||||
|
return ite;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
iterator begin() {
|
iterator begin() {
|
||||||
@ -224,6 +242,14 @@ public:
|
|||||||
void erase(iterator target) {
|
void erase(iterator target) {
|
||||||
erase(target - begin());
|
erase(target - begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void reverse() {
|
||||||
|
MyVector<T> tmp = *this;
|
||||||
|
for (size_t i = 0; i < m_size / 2; ++i) {
|
||||||
|
std::swap(tmp[i], tmp[m_size - i - 1]);
|
||||||
|
}
|
||||||
|
*this = tmp;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MY_VECTOR_H
|
#endif // MY_VECTOR_H
|
||||||
|
@ -1,14 +1,148 @@
|
|||||||
#ifndef ACTIONMANAGER_H
|
#ifndef ACTIONMANAGER_H
|
||||||
#define ACTIONMANAGER_H
|
#define ACTIONMANAGER_H
|
||||||
|
|
||||||
enum class EditAction {
|
#include "../mystl/my_stack.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
enum class EditActiontype {
|
||||||
Initialize,
|
Initialize,
|
||||||
Insert,
|
Insert,
|
||||||
Delete,
|
Delete,
|
||||||
};
|
};
|
||||||
|
|
||||||
class ActionManager {
|
struct EditAction {
|
||||||
|
EditActiontype type;
|
||||||
|
int pos;
|
||||||
|
std::string content;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ActionManager {
|
||||||
|
private:
|
||||||
|
MyStack<MyVector<EditAction>> undoStack_, redoStack_;
|
||||||
|
std::string content_;
|
||||||
|
|
||||||
|
MyVector<EditAction> calculateEditActions(const std::string &str1, const std::string &str2) { // 规定Editor只会在删除或者插入时提交,因此只会同时存在一种操作
|
||||||
|
int m = str1.length();
|
||||||
|
int n = str2.length();
|
||||||
|
MyVector<MyVector<int>> dp(m + 1, MyVector<int>(n + 1));
|
||||||
|
|
||||||
|
for (int i = 0; i <= m; ++i) {
|
||||||
|
dp[i][0] = i;
|
||||||
|
}
|
||||||
|
for (int j = 0; j <= n; ++j) {
|
||||||
|
dp[0][j] = j;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i <= m; ++i) {
|
||||||
|
for (int j = 1; j <= n; ++j) {
|
||||||
|
if (str1[i - 1] == str2[j - 1]) {
|
||||||
|
dp[i][j] = dp[i - 1][j - 1];
|
||||||
|
} else {
|
||||||
|
dp[i][j] = std::min(dp[i - 1][j], dp[i][j - 1]) + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 回溯以找到编辑操作
|
||||||
|
MyVector<EditAction> actions;
|
||||||
|
int i = m, j = n;
|
||||||
|
while (i > 0 && j > 0) {
|
||||||
|
if (str1[i - 1] == str2[j - 1]) {
|
||||||
|
--i;
|
||||||
|
--j;
|
||||||
|
} else if (dp[i][j] == dp[i - 1][j] + 1) {
|
||||||
|
actions.push_back({EditActiontype::Delete, i - 1, std::string(1, str1[i - 1])});
|
||||||
|
--i;
|
||||||
|
} else if (dp[i][j] == dp[i][j - 1] + 1) {
|
||||||
|
actions.push_back({EditActiontype::Insert, i, std::string(1, str2[j - 1])});
|
||||||
|
--j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (i > 0) {
|
||||||
|
actions.push_back({EditActiontype::Delete, i - 1, std::string(1, str1[i - 1])});
|
||||||
|
--i;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (j > 0) {
|
||||||
|
actions.push_back({EditActiontype::Insert, i, std::string(1, str2[j - 1])});
|
||||||
|
--j;
|
||||||
|
}
|
||||||
|
|
||||||
|
actions.reverse();
|
||||||
|
|
||||||
|
// 考虑到先前进行的插入和删除操作,对随后插入和删除的位置进行修正
|
||||||
|
int offset = 0;
|
||||||
|
for (int i = 0; i < actions.size(); ++i) {
|
||||||
|
if (actions[i].type == EditActiontype::Insert) {
|
||||||
|
actions[i].pos += offset;
|
||||||
|
offset++;
|
||||||
|
} else if (actions[i].type == EditActiontype::Delete) {
|
||||||
|
actions[i].pos += offset;
|
||||||
|
offset--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string applyEditAction(MyVector<EditAction> &actions, std::string &content) {
|
||||||
|
std::string newContent = content;
|
||||||
|
for(int i = 0; i < actions.size(); i++) {
|
||||||
|
if(actions[i].type == EditActiontype::Insert) {
|
||||||
|
newContent.insert(actions[i].pos, actions[i].content);
|
||||||
|
} else if(actions[i].type == EditActiontype::Delete) {
|
||||||
|
newContent.erase(actions[i].pos, actions[i].content.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
ActionManager() {
|
||||||
|
}
|
||||||
|
ActionManager(const std::string &content) {
|
||||||
|
content_ = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateContent(const std::string &content) {
|
||||||
|
redoStack_.clear();
|
||||||
|
MyVector<EditAction> actions = calculateEditActions(content_, content);
|
||||||
|
content_ = content;
|
||||||
|
undoStack_.push(actions);
|
||||||
|
}
|
||||||
|
|
||||||
|
void undo() {
|
||||||
|
if (undoStack_.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MyVector<EditAction> actions = undoStack_.top();
|
||||||
|
undoStack_.pop();
|
||||||
|
std::string newContent = applyEditAction(actions, content_);
|
||||||
|
redoStack_.push(calculateEditActions(content_, newContent));
|
||||||
|
content_ = newContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void redo() {
|
||||||
|
if (redoStack_.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MyVector<EditAction> actions = redoStack_.top();
|
||||||
|
redoStack_.pop();
|
||||||
|
std::string newContent = applyEditAction(actions, content_);
|
||||||
|
undoStack_.push(calculateEditActions(content_, newContent));
|
||||||
|
content_ = newContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setContent(const std::string &content) {
|
||||||
|
content_ = content;
|
||||||
|
undoStack_.clear();
|
||||||
|
redoStack_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getContent() {
|
||||||
|
return content_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
23
utils/ActionManager_test.cpp
Normal file
23
utils/ActionManager_test.cpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "ActionManager.h"
|
||||||
|
#include "../mystl/my_vector.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
ActionManager am;
|
||||||
|
MyVector<EditAction> v;
|
||||||
|
v = am.calculateEditActions("i can see you, but u dont love me", "i cant hug u, but i love you");
|
||||||
|
printf("Actions: %zu\n", v.size());
|
||||||
|
//replay test
|
||||||
|
std::string s1 = "i can see you, but u dont love me";
|
||||||
|
for(int i = 0; i < v.size(); i++) {
|
||||||
|
if(v[i].type == EditActiontype::Insert) {
|
||||||
|
s1.insert(v[i].pos, v[i].content);
|
||||||
|
} else if(v[i].type == EditActiontype::Delete) {
|
||||||
|
s1.erase(v[i].pos, v[i].content.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("%s\n", s1.c_str());
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user