Modules/Containers/outdated/public/PersistentList.h
2023-07-07 00:11:04 +03:00

115 lines
No EOL
2.3 KiB
C++

#pragma once
#include "List.h"
namespace tp {
// TODO : insert and remove by range
// IN DEVELOPMENT
template <typename Type>
class PersistentList {
public:
struct UndoNode {
ListNode<Type>* mNode = NULL;
enum { NONE, ADD, REMOVE, UNDO_MARK } mType = NONE;
};
private:
List<Type> mList;
List<UndoNode> mHystory;
ListNode<UndoNode>* mCurrentState = NULL;
void clearFuture() {
auto iter = mHystory.last();
while (iter && iter != mCurrentState) {
auto del = iter;
iter = iter->prev;
mHystory.detach(del);
mHystory.deleteNode(del);
}
}
public:
PersistentList() {
pushUndoPoint();
}
void pushUndoPoint() {
mHystory.pushBack(UndoNode{ 0, UndoNode::UNDO_MARK });
mCurrentState = mHystory.last();
}
const List<Type>& list() const {
return mList;
}
const List<UndoNode>& hystory() const {
return mHystory;
}
// returns new node inserted after aNode
ListNode<Type>* insertAfter(ListNode<Type>* aNode) {
clearFuture();
auto node = mList.newNode();
mList.attach(node, aNode);
mHystory.pushBack(UndoNode{ node, UndoNode::ADD });
return node;
}
void remove(ListNode<Type>* aNode) {
clearFuture();
mHystory.pushBack(UndoNode{ aNode, UndoNode::REMOVE });
mList.detach(aNode);
}
void undo() {
if (!mCurrentState->prev) {
return;
}
while (mCurrentState->data.mType != UndoNode::UNDO_MARK) {
if (mCurrentState->data.mType != UndoNode::ADD) {
mList.detach(mCurrentState->data.mNode);
}
else {
mList.attach(mCurrentState->data.mNode, mCurrentState->data.mNode->prev);
}
mCurrentState = mCurrentState->prev;
}
}
void redo() {
if (!mCurrentState->next) {
return;
}
while (mCurrentState->data.mType != UndoNode::UNDO_MARK) {
if (mCurrentState->data.mType != UndoNode::ADD) {
mList.attach(mCurrentState->data.mNode, mCurrentState->data.mNode->prev);
}
else {
mList.detach(mCurrentState->data.mNode);
}
mCurrentState = mCurrentState->next;
}
}
void clearHystory() {
// TODO : mem leaks
//for (auto node : mHystory) {
//delete node->data();
//}
//mHystory.free();
}
~PersistentList() {
}
};
};