74 lines
2.9 KiB
C++
74 lines
2.9 KiB
C++
#include "undohistory.h"
|
|
#include "common.h"
|
|
#include "objects/service/selection.h"
|
|
|
|
void UndoHistory::PushState(UndoState state) {
|
|
if (processingUndo) return; // Ignore PushState requests when changes are initiated by us
|
|
redoHistory = {};
|
|
|
|
if (maxBufferSize != -1 && (int)undoHistory.size() > maxBufferSize)
|
|
undoHistory.erase(undoHistory.begin(), undoHistory.begin()+maxBufferSize-(int)undoHistory.size()-1);
|
|
|
|
undoHistory.push_back(state);
|
|
undoStateListener(!undoHistory.empty(), !redoHistory.empty());
|
|
}
|
|
|
|
void UndoHistory::Undo() {
|
|
if (undoHistory.size() == 0) return;
|
|
UndoState state = undoHistory.back();
|
|
undoHistory.pop_back();
|
|
redoHistory.push(state);
|
|
|
|
processingUndo = true;
|
|
|
|
for (UndoStateChange& change : state) {
|
|
// https://stackoverflow.com/a/63483353
|
|
if (auto v = std::get_if<UndoStatePropertyChanged>(&change)) {
|
|
// The old value used to be valid, so it still should be...
|
|
v->affectedInstance->SetProperty(v->property, v->oldValue).expect();
|
|
} else if (auto v = std::get_if<UndoStateInstanceCreated>(&change)) {
|
|
v->instance->SetParent(std::nullopt);
|
|
} else if (auto v = std::get_if<UndoStateInstanceRemoved>(&change)) {
|
|
v->instance->SetParent(v->oldParent);
|
|
} else if (auto v = std::get_if<UndoStateInstanceReparented>(&change)) {
|
|
v->instance->SetParent(v->oldParent);
|
|
} else if (auto v = std::get_if<UndoStateSelectionChanged>(&change)) {
|
|
gDataModel->GetService<Selection>()->Set(v->oldSelection);
|
|
}
|
|
}
|
|
|
|
processingUndo = false;
|
|
undoStateListener(!undoHistory.empty(), !redoHistory.empty());
|
|
}
|
|
|
|
void UndoHistory::Redo() {
|
|
if (redoHistory.size() == 0) return;
|
|
UndoState state = redoHistory.top();
|
|
redoHistory.pop();
|
|
undoHistory.push_back(state);
|
|
|
|
processingUndo = true;
|
|
|
|
for (UndoStateChange& change : state) {
|
|
// https://stackoverflow.com/a/63483353
|
|
if (auto v = std::get_if<UndoStatePropertyChanged>(&change)) {
|
|
// The old value used to be valid, so it still should be...
|
|
v->affectedInstance->SetProperty(v->property, v->newValue).expect();
|
|
} else if (auto v = std::get_if<UndoStateInstanceCreated>(&change)) {
|
|
v->instance->SetParent(v->newParent);
|
|
} else if (auto v = std::get_if<UndoStateInstanceRemoved>(&change)) {
|
|
v->instance->SetParent(std::nullopt);
|
|
} else if (auto v = std::get_if<UndoStateInstanceReparented>(&change)) {
|
|
v->instance->SetParent(v->newParent);
|
|
} else if (auto v = std::get_if<UndoStateSelectionChanged>(&change)) {
|
|
gDataModel->GetService<Selection>()->Set(v->newSelection);
|
|
}
|
|
}
|
|
|
|
processingUndo = false;
|
|
undoStateListener(!undoHistory.empty(), !redoHistory.empty());
|
|
}
|
|
|
|
void UndoHistory::SetUndoStateListener(UndoStateChangedListener listener) {
|
|
undoStateListener = listener;
|
|
}
|