rocket/synceditdata.h
Erik Faye-Lund d54d8587c9 more. stuff.
2010-03-19 17:40:59 +01:00

205 lines
3.8 KiB
C++

#pragma once
#include "syncdata.h"
#include <stack>
#include <list>
class SyncEditData : public SyncData
{
public:
SyncEditData() : SyncData() {}
class Command
{
public:
virtual ~Command() {}
virtual void exec(SyncEditData *data) = 0;
virtual void undo(SyncEditData *data) = 0;
};
class InsertCommand : public Command
{
public:
InsertCommand(size_t track, size_t row, const SyncTrack::KeyFrame &key) : track(track), row(row), key(key) {}
~InsertCommand() {}
virtual void exec(SyncEditData *data)
{
SyncTrack &track = data->getTrack(this->track);
assert(!track.isKeyFrame(row));
track.setKeyFrame(row, key);
}
virtual void undo(SyncEditData *data)
{
SyncTrack &track = data->getTrack(this->track);
assert(track.isKeyFrame(row));
track.deleteKeyFrame(row);
}
private:
size_t track, row;
SyncTrack::KeyFrame key;
};
class DeleteCommand : public Command
{
public:
DeleteCommand(size_t track, size_t row) : track(track), row(row) {}
~DeleteCommand() {}
virtual void exec(SyncEditData *data)
{
SyncTrack &track = data->getTrack(this->track);
assert(track.isKeyFrame(row));
oldKey = *track.getKeyFrame(row);
track.deleteKeyFrame(row);
}
virtual void undo(SyncEditData *data)
{
SyncTrack &track = data->getTrack(this->track);
assert(!track.isKeyFrame(row));
track.setKeyFrame(row, oldKey);
}
private:
size_t track, row;
SyncTrack::KeyFrame oldKey;
};
class EditCommand : public Command
{
public:
EditCommand(size_t track, size_t row, const SyncTrack::KeyFrame &key) : track(track), row(row), key(key) {}
~EditCommand() {}
virtual void exec(SyncEditData *data)
{
SyncTrack &track = data->getTrack(this->track);
// store old key
assert(track.isKeyFrame(row));
oldKey = *track.getKeyFrame(row);
// update
track.setKeyFrame(row, key);
}
virtual void undo(SyncEditData *data)
{
SyncTrack &track = data->getTrack(this->track);
assert(track.isKeyFrame(row));
track.setKeyFrame(row, oldKey);
}
private:
size_t track, row;
SyncTrack::KeyFrame oldKey, key;
};
class MultiCommand : public Command
{
public:
~MultiCommand()
{
std::list<Command*>::iterator it;
for (it = commands.begin(); it != commands.end(); ++it)
{
delete *it;
}
commands.clear();
}
void addEditCommand(Command *cmd)
{
commands.push_back(cmd);
}
virtual void exec(SyncEditData *data)
{
std::list<Command*>::iterator it;
for (it = commands.begin(); it != commands.end(); ++it) (*it)->exec(data);
}
virtual void undo(SyncEditData *data)
{
std::list<Command*>::iterator it;
for (it = commands.begin(); it != commands.end(); ++it) (*it)->undo(data);
}
private:
std::list<Command*> commands;
};
void exec(Command *cmd)
{
undoStack.push(cmd);
cmd->exec(this);
clearRedoStack();
}
bool undo()
{
if (undoStack.size() == 0) return false;
Command *cmd = undoStack.top();
undoStack.pop();
redoStack.push(cmd);
cmd->undo(this);
return true;
}
bool redo()
{
if (redoStack.size() == 0) return false;
Command *cmd = redoStack.top();
redoStack.pop();
undoStack.push(cmd);
cmd->exec(this);
return true;
}
void clearRedoStack()
{
while (!redoStack.empty())
{
Command *cmd = redoStack.top();
redoStack.pop();
delete cmd;
}
}
void setKey(int track, int row, float val)
{
SyncTrack &t = getTrack(track);
SyncEditData::Command *cmd;
if (t.isKeyFrame(row))
{
cmd = new EditCommand(track, row, val);
}
else
{
cmd = new InsertCommand(track, row, val);
}
exec(cmd);
}
void deleteKey(int track, int row)
{
assert(getTrack(track).isKeyFrame(row));
Command *cmd = new DeleteCommand(track, row);
exec(cmd);
}
private:
std::stack<Command*> undoStack;
std::stack<Command*> redoStack;
};