rocket/trackview.h
2010-03-19 17:40:56 +01:00

233 lines
4.9 KiB
C++

#pragma once
#include "syncdata.h"
#include <list>
#include <string>
#include <stack>
class SyncData;
class SyncDataEdit
{
public:
SyncDataEdit() : syncData(NULL) {}
void setSyncData(SyncData *syncData) { this->syncData = syncData; }
SyncData *getSyncData() { return syncData; }
class Command
{
public:
virtual ~Command() {}
virtual void exec(SyncDataEdit *data) = 0;
virtual void undo(SyncDataEdit *data) = 0;
};
class EditCommand : public Command
{
public:
EditCommand(int track, int row, bool existing, float value) : track(track), row(row), newValExisting(existing), newVal(value) {}
~EditCommand() {}
virtual void exec(SyncDataEdit *data)
{
SyncTrack &track = data->getSyncData()->getTrack(this->track);
// store old state
oldValExisting = track.isKeyFrame(row);
if (oldValExisting) oldVal = track.getKeyFrame(row)->value;
// update
if (!newValExisting) track.deleteKeyFrame(row);
else track.setKeyFrame(row, newVal);
}
virtual void undo(SyncDataEdit *data)
{
SyncTrack &track = data->getSyncData()->getTrack(this->track);
// un-update
if (!oldValExisting) track.deleteKeyFrame(row);
else track.setKeyFrame(row, oldVal);
}
private:
int track, row;
float newVal, oldVal;
bool newValExisting, oldValExisting;
};
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;
}
}
private:
std::stack<Command*> undoStack;
std::stack<Command*> redoStack;
SyncData *syncData;
};
// custom messages
#define WM_REDO (WM_USER + 1)
class TrackView
{
public:
TrackView();
~TrackView();
HWND create(HINSTANCE hInstance, HWND hwndParent);
HWND getWin(){ return hwnd; }
void setSyncData(SyncData *syncData) { this->syncDataEdit.setSyncData(syncData); }
SyncData *getSyncData() { return syncDataEdit.getSyncData(); }
private:
// some nasty hackery to forward the window messages
friend static LRESULT CALLBACK trackViewWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT windowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
// events
LRESULT onCreate();
LRESULT onPaint();
LRESULT onVScroll(UINT sbCode, int newPos);
LRESULT onHScroll(UINT sbCode, int newPos);
LRESULT onSize(int width, int height);
LRESULT onKeyDown(UINT keyCode, UINT flags);
LRESULT onChar(UINT keyCode, UINT flags);
// the window procedure
void paintTracks(HDC hdc, RECT rcTracks);
void paintTopMargin(HDC hdc, RECT rcTracks);
void setupScrollBars();
void setScrollPos(int newScrollPosX, int newScrollPosY);
void scrollWindow(int newScrollPosX, int newScrollPosY);
void invalidateRange(int startTrack, int stopTrack, int startRow, int stopRow)
{
RECT rect;
rect.left = getScreenX(min(startTrack, stopTrack));
rect.right = getScreenX(max(startTrack, stopTrack) + 1);
rect.top = getScreenY(min(startRow, stopRow));
rect.bottom = getScreenY(max(startRow, stopRow) + 1);
InvalidateRect(hwnd, &rect, TRUE);
}
void invalidatePos(int track, int row)
{
RECT rect;
rect.left = getScreenX(track);
rect.right = getScreenX(track + 1);
rect.top = getScreenY(row);
rect.bottom = getScreenY(row + 1);
InvalidateRect(hwnd, &rect, TRUE);
}
void invalidateRow(int row)
{
RECT clientRect;
GetClientRect(hwnd, &clientRect);
RECT rect;
rect.left = clientRect.left;
rect.right = clientRect.right;
rect.top = getScreenY(row);
rect.bottom = getScreenY(row + 1);
InvalidateRect(hwnd, &rect, TRUE);
}
void invalidateTrack(int track)
{
RECT clientRect;
GetClientRect(hwnd, &clientRect);
RECT rect;
rect.left = getScreenX(track);
rect.right = getScreenX(track + 1);
rect.top = clientRect.top;
rect.bottom = clientRect.bottom;
InvalidateRect(hwnd, &rect, TRUE);
}
void setEditRow(int newEditRow);
void setEditTrack(int newEditTrack);
int getScreenY(int row);
int getScreenX(int track);
int getTrackCount()
{
SyncData *syncData = getSyncData();
if (NULL == syncData) return 0;
return int(syncData->getTrackCount());
};
bool selectActive;
int selectStartTrack, selectStopTrack;
int selectStartRow, selectStopRow;
HBRUSH selectBaseBrush, selectDarkBrush;
/* cursor position */
int editRow, editTrack;
int scrollPosX, scrollPosY;
int windowWidth, windowHeight;
int windowRows, windowTracks;
SyncDataEdit syncDataEdit;
std::basic_string<TCHAR> editString;
HWND hwnd;
HBRUSH editBrush;
};
ATOM registerTrackViewWindowClass(HINSTANCE hInstance);