editor: replace document when loading

Simplify the book-keeping a bit by simply creating a new document
when loading. Copy the ClientSocket to the new document to keep
client-state.
This commit is contained in:
Erik Faye-Lund 2011-03-02 18:21:56 +01:00
parent 9132474bdb
commit 3178f22c2a
4 changed files with 100 additions and 80 deletions

View File

@ -59,7 +59,6 @@ HWND hwnd = NULL;
TrackView *trackView = NULL;
HWND trackViewWin = NULL;
HWND statusBarWin = NULL;
SyncDocument document;
HKEY regConfigKey = NULL;
RecentFiles mruFileList(NULL);
@ -190,38 +189,64 @@ HMENU findSubMenuContaining(HMENU menu, UINT id)
return (HMENU)0;
}
void fileNew()
void setDocument(SyncDocument *newDoc)
{
// document.purgeUnusedTracks();
SyncDocument::MultiCommand *multiCmd = new SyncDocument::MultiCommand();
for (size_t i = 0; i < document.num_tracks; ++i) {
sync_track *t = document.tracks[i];
for (size_t j = 0; j < t->num_keys; ++j)
multiCmd->addCommand(new SyncDocument::DeleteCommand(i, t->keys[j].row));
SyncDocument *oldDoc = trackView->getDocument();
if (oldDoc && oldDoc->clientSocket.connected()) {
// delete old key-frames
for (size_t i = 0; i < oldDoc->num_tracks; ++i) {
sync_track *t = oldDoc->tracks[i];
for (size_t j = 0; j < t->num_keys; ++j)
oldDoc->clientSocket.sendDeleteKeyCommand(t->name, t->keys[j].row);
}
if (newDoc) {
// add back missing client-tracks
std::map<const std::string, size_t>::const_iterator it;
for (it = oldDoc->clientSocket.clientTracks.begin(); it != oldDoc->clientSocket.clientTracks.end(); ++it) {
int trackIndex = sync_find_track(newDoc, it->first.c_str());
if (0 > trackIndex)
trackIndex = int(newDoc->createTrack(it->first.c_str()));
}
// copy socket and update client
newDoc->clientSocket = oldDoc->clientSocket;
for (size_t i = 0; i < newDoc->num_tracks; ++i) {
sync_track *t = newDoc->tracks[i];
for (size_t j = 0; j < t->num_keys; ++j)
newDoc->clientSocket.sendSetKeyCommand(t->name, t->keys[j]);
}
}
}
document.exec(multiCmd);
setWindowFileName(L"Untitled");
document.fileName.clear();
trackView->setDocument(newDoc);
SendMessage(hwnd, WM_CURRVALDIRTY, 0, 0);
InvalidateRect(trackViewWin, NULL, FALSE);
document.clearUndoStack();
document.clearRedoStack();
if (oldDoc)
delete oldDoc;
}
void fileNew()
{
setDocument(new SyncDocument);
setWindowFileName(L"Untitled");
}
void loadDocument(const std::wstring &_fileName)
{
if (document.load(_fileName)) {
setWindowFileName(_fileName.c_str());
SyncDocument *newDoc = SyncDocument::load(_fileName);
if (newDoc) {
// update MRU list
mruFileList.insert(_fileName);
mruFileList.update();
DrawMenuBar(hwnd);
trackView->setDocument(&document);
SendMessage(hwnd, WM_CURRVALDIRTY, 0, 0);
InvalidateRect(trackViewWin, NULL, FALSE);
// set new document
setDocument(newDoc);
setWindowFileName(_fileName.c_str());
}
else
error("failed to open file");
@ -261,10 +286,11 @@ bool fileSaveAs()
ofn.Flags = OFN_SHOWHELP | OFN_OVERWRITEPROMPT;
if (GetSaveFileNameW(&ofn)) {
if (document.save(temp)) {
document.clientSocket.sendSaveCommand();
SyncDocument *doc = trackView->getDocument();
if (doc->save(temp)) {
doc->clientSocket.sendSaveCommand();
setWindowFileName(temp);
document.fileName = temp;
doc->fileName = temp;
mruFileList.insert(temp);
mruFileList.update();
@ -278,11 +304,12 @@ bool fileSaveAs()
bool fileSave()
{
if (document.fileName.empty())
SyncDocument *doc = trackView->getDocument();
if (doc->fileName.empty())
return fileSaveAs();
if (!document.save(document.fileName)) {
document.clientSocket.sendSaveCommand();
if (!doc->save(doc->fileName)) {
doc->clientSocket.sendSaveCommand();
error("Failed to save file");
return false;
}
@ -291,8 +318,8 @@ bool fileSave()
void attemptQuit()
{
if (document.modified())
{
SyncDocument *doc = trackView->getDocument();
if (doc->modified()) {
UINT res = MessageBox(hwnd, "Save before exit?", mainWindowTitle, MB_YESNOCANCEL | MB_ICONQUESTION);
if ((IDYES == res && fileSave()) || (IDNO == res))
DestroyWindow(hwnd);
@ -325,6 +352,7 @@ static HWND createStatusBar(HINSTANCE hInstance, HWND hpwnd)
static LRESULT CALLBACK mainWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
SyncDocument *doc = trackView ? trackView->getDocument() : NULL;
switch(msg)
{
case WM_CREATE:
@ -415,7 +443,7 @@ static LRESULT CALLBACK mainWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARA
break;
case ID_FILE_REMOTEEXPORT:
document.clientSocket.sendSaveCommand();
doc->clientSocket.sendSaveCommand();
break;
case ID_RECENTFILES_FILE1:
@ -482,8 +510,8 @@ static LRESULT CALLBACK mainWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARA
case WM_CURRVALDIRTY:
{
char temp[256];
if (document.num_tracks > 0) {
const sync_track *t = document.tracks[document.getTrackIndexFromPos(trackView->getEditTrack())];
if (doc->num_tracks > 0) {
const sync_track *t = doc->tracks[doc->getTrackIndexFromPos(trackView->getEditTrack())];
int row = trackView->getEditRow();
int idx = key_idx_floor(t, row);
snprintf(temp, 256, "%f", sync_get_val(t, row));
@ -557,6 +585,7 @@ SOCKET clientConnect(SOCKET serverSocket, sockaddr_in *host)
size_t clientIndex;
void processCommand(ClientSocket &sock)
{
SyncDocument *doc = trackView->getDocument();
int strLen, serverIndex, newRow;
std::string trackName;
const sync_track *t;
@ -575,19 +604,19 @@ void processCommand(ClientSocket &sock)
return;
// find track
serverIndex = sync_find_track(&document,
serverIndex = sync_find_track(doc,
trackName.c_str());
if (0 > serverIndex)
serverIndex =
int(document.createTrack(trackName));
int(doc->createTrack(trackName));
// setup remap
document.clientSocket.clientTracks[trackName] = clientIndex++;
doc->clientSocket.clientTracks[trackName] = clientIndex++;
// send key-frames
t = document.tracks[serverIndex];
t = doc->tracks[serverIndex];
for (int i = 0; i < (int)t->num_keys; ++i)
document.clientSocket.sendSetKeyCommand(trackName,
doc->clientSocket.sendSetKeyCommand(trackName,
t->keys[i]);
InvalidateRect(trackViewWin, NULL, FALSE);
@ -641,8 +670,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/,
die("Window Registration Failed!");
trackView = new TrackView();
trackView->setDocument(&document);
hwnd = CreateWindowExW(
0,
mainWindowClassName,
@ -666,10 +694,9 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/,
bool done = false;
MSG msg;
bool guiConnected = false;
while (!done)
{
if (!document.clientSocket.connected())
{
while (!done) {
SyncDocument *doc = trackView->getDocument();
if (!doc->clientSocket.connected()) {
SOCKET clientSocket = INVALID_SOCKET;
fd_set fds;
FD_ZERO(&fds);
@ -690,26 +717,26 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/,
char temp[256];
snprintf(temp, 256, "Connected to %s", inet_ntoa(client.sin_addr));
SendMessage(statusBarWin, SB_SETTEXT, 0, (LPARAM)temp);
document.clientSocket = ClientSocket(clientSocket);
doc->clientSocket = ClientSocket(clientSocket);
clientIndex = 0;
document.clientSocket.sendPauseCommand(true);
document.clientSocket.sendSetRowCommand(trackView->getEditRow());
doc->clientSocket.sendPauseCommand(true);
doc->clientSocket.sendSetRowCommand(trackView->getEditRow());
guiConnected = true;
}
else SendMessage(statusBarWin, SB_SETTEXT, 0, (LPARAM)"Not Connected.");
}
}
if (document.clientSocket.connected()) {
ClientSocket &clientSocket = document.clientSocket;
if (doc->clientSocket.connected()) {
ClientSocket &clientSocket = doc->clientSocket;
// look for new commands
while (clientSocket.pollRead())
processCommand(clientSocket);
}
if (!document.clientSocket.connected() && guiConnected) {
document.clientSocket.clientPaused = true;
if (!doc->clientSocket.connected() && guiConnected) {
doc->clientSocket.clientPaused = true;
InvalidateRect(trackViewWin, NULL, FALSE);
SendMessage(statusBarWin, SB_SETTEXT, 0, (LPARAM)"Not Connected.");
guiConnected = false;

View File

@ -10,21 +10,22 @@ SyncDocument::~SyncDocument()
#import <msxml3.dll> named_guids
bool SyncDocument::load(const std::wstring &fileName)
SyncDocument *SyncDocument::load(const std::wstring &fileName)
{
SyncDocument *ret = new SyncDocument;
ret->fileName = fileName;
MSXML2::IXMLDOMDocumentPtr doc(MSXML2::CLSID_DOMDocument);
try {
SyncDocument::MultiCommand *multiCmd = new SyncDocument::MultiCommand();
for (size_t i = 0; i < num_tracks; ++i) {
sync_track *t = tracks[i];
for (size_t j = 0; j < t->num_keys; ++j)
multiCmd->addCommand(new SyncDocument::DeleteCommand(i, t->keys[j].row));
}
doc->load(fileName.c_str());
MSXML2::IXMLDOMNamedNodeMapPtr attribs = doc->documentElement->Getattributes();
MSXML2::IXMLDOMNodePtr rowsParam = attribs->getNamedItem("rows");
if (rowsParam) {
std::string rowsString = rowsParam->Gettext();
ret->setRows(atoi(rowsString.c_str()));
}
MSXML2::IXMLDOMNodeListPtr trackNodes = doc->documentElement->selectNodes("track");
for (int i = 0; i < trackNodes->Getlength(); ++i)
{
@ -34,8 +35,8 @@ bool SyncDocument::load(const std::wstring &fileName)
std::string name = attribs->getNamedItem("name")->Gettext();
// look up track-name, create it if it doesn't exist
int trackIndex = sync_find_track(this, name.c_str());
if (0 > trackIndex) trackIndex = int(createTrack(name));
int trackIndex = sync_find_track(ret, name.c_str());
if (0 > trackIndex) trackIndex = int(ret->createTrack(name));
MSXML2::IXMLDOMNodeListPtr rowNodes = trackNode->GetchildNodes();
for (int i = 0; i < rowNodes->Getlength(); ++i)
@ -53,34 +54,23 @@ bool SyncDocument::load(const std::wstring &fileName)
k.row = atoi(rowString.c_str());
k.value = float(atof(valueString.c_str()));
k.type = key_type(atoi(interpolationString.c_str()));
multiCmd->addCommand(new InsertCommand(int(trackIndex), k));
assert(!is_key_frame(ret->tracks[trackIndex], key.row));
if (sync_set_key(ret->tracks[trackIndex], &k))
throw std::bad_alloc("sync_set_key");
}
}
}
MSXML2::IXMLDOMNodePtr rowsParam = attribs->getNamedItem("rows");
if (rowsParam) {
std::string rowsString = rowsParam->Gettext();
this->setRows(atoi(rowsString.c_str()));
}
this->fileName = fileName;
clearUndoStack();
clearRedoStack();
this->exec(multiCmd);
savePointDelta = 0;
savePointUnreachable = false;
}
catch(_com_error &e)
{
char temp[256];
_snprintf(temp, 256, "Error loading: %s\n", (const char*)_bstr_t(e.Description()));
MessageBox(NULL, temp, NULL, MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
return false;
return NULL;
}
return true;
return ret;
}
bool SyncDocument::save(const std::wstring &fileName)

View File

@ -256,8 +256,8 @@ public:
assert(t2 < trackOrder.size());
std::swap(trackOrder[t1], trackOrder[t2]);
}
bool load(const std::wstring &fileName);
static SyncDocument *load(const std::wstring &fileName);
bool save(const std::wstring &fileName);
bool modified()

View File

@ -34,7 +34,8 @@ static int getMaxCharacterWidthFromString(HDC hdc, const char *chars)
return getMaxCharacterWidth(hdc, chars, strlen(chars));
}
TrackView::TrackView()
TrackView::TrackView() :
document(NULL)
{
scrollPosX = 0;
scrollPosY = 0;
@ -82,6 +83,8 @@ TrackView::~TrackView()
DeleteObject(editBrush);
DeleteObject(rowPen);
DeleteObject(rowSelectPen);
if (document)
delete document;
}
void TrackView::setFont(HFONT font)