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

View File

@ -10,21 +10,22 @@ SyncDocument::~SyncDocument()
#import <msxml3.dll> named_guids #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); MSXML2::IXMLDOMDocumentPtr doc(MSXML2::CLSID_DOMDocument);
try { 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()); doc->load(fileName.c_str());
MSXML2::IXMLDOMNamedNodeMapPtr attribs = doc->documentElement->Getattributes(); 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"); MSXML2::IXMLDOMNodeListPtr trackNodes = doc->documentElement->selectNodes("track");
for (int i = 0; i < trackNodes->Getlength(); ++i) 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(); std::string name = attribs->getNamedItem("name")->Gettext();
// look up track-name, create it if it doesn't exist // look up track-name, create it if it doesn't exist
int trackIndex = sync_find_track(this, name.c_str()); int trackIndex = sync_find_track(ret, name.c_str());
if (0 > trackIndex) trackIndex = int(createTrack(name)); if (0 > trackIndex) trackIndex = int(ret->createTrack(name));
MSXML2::IXMLDOMNodeListPtr rowNodes = trackNode->GetchildNodes(); MSXML2::IXMLDOMNodeListPtr rowNodes = trackNode->GetchildNodes();
for (int i = 0; i < rowNodes->Getlength(); ++i) 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.row = atoi(rowString.c_str());
k.value = float(atof(valueString.c_str())); k.value = float(atof(valueString.c_str()));
k.type = key_type(atoi(interpolationString.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) catch(_com_error &e)
{ {
char temp[256]; char temp[256];
_snprintf(temp, 256, "Error loading: %s\n", (const char*)_bstr_t(e.Description())); _snprintf(temp, 256, "Error loading: %s\n", (const char*)_bstr_t(e.Description()));
MessageBox(NULL, temp, NULL, MB_OK | MB_ICONERROR | MB_SETFOREGROUND); 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) bool SyncDocument::save(const std::wstring &fileName)

View File

@ -257,7 +257,7 @@ public:
std::swap(trackOrder[t1], trackOrder[t2]); 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 save(const std::wstring &fileName);
bool modified() bool modified()

View File

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