123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419 |
- /* GCSx
- ** FOLDER.CPP
- **
- ** Folders within world browser (user-definable)
- */
- /*****************************************************************************
- ** Copyright (C) 2003-2006 Janson
- **
- ** This program is free software; you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation; either version 2 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program; if not, write to the Free Software
- ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
- *****************************************************************************/
- #include "all.h"
- FolderEdit::FolderEdit(WorldEdit* myWorld, int myId) : items() { start_func
- assert(myWorld);
-
- id = myId;
- cached = 0;
- lockCount = 0;
- cacheFile = NULL;
- world = myWorld;
-
- sorted = 1;
- defaultFont = 0;
- defaultTileSet = 0;
- defaultScene = 0;
- defaultAnimGroup = 0;
- defaultScript = 0;
- defaultLibrary = 0;
- icon = 0;
- // Use an "Untitled" name
- if (myId) {
- name = "New Folder";
- headerModified = contentModified = 1;
- }
- else {
- name = blankString;
- headerModified = contentModified = 0;
- }
- browserNode = NULL;
- disassociated = 0;
- desktop->broadcastObjChange(OBJ_FOLDER | OBJMOD_CREATE, this, 0, 0);
- }
- FolderEdit::~FolderEdit() { start_func
- delete cacheFile;
- // @TODO: doesn't appear to be needed; no way to delete accidentally
- // if (!disassociated) desktop->broadcastObjChange(OBJ_FOLDER | OBJMOD_DELETE, this, 0, 0);
- // World should be the one deleting us, which will delete our node also
- }
-
- void FolderEdit::cacheLoad() throw_File { start_func
- if (cached) {
- // load into memory
- assert(cacheFile);
- assert(cacheFile->getVersion() <= 1);
-
- /*
- cacheFile->rewind();
-
- try {
- // (this is where we would load content, if folders had any)
- }
- catch (...) {
- // Recache ourselves
- throw;
- }
- */
-
- // We retain this pointer and reuse it IF we
- // unlock to 0 AND aren't modified
- cached = 0;
- }
- }
- void FolderEdit::loadHeader(FileRead* file) throw_File { start_func
- assert(items.empty());
- if (file->getVersion() > 1) {
- throw FileException("Unsupported folder version %d", file->getVersion());
- }
- file->readStr(name);
- id = file->readInt();
- sorted = file->readInt();
- defaultFont = file->readInt();
- defaultTileSet = file->readInt();
- defaultScene = file->readInt();
- defaultAnimGroup = file->readInt();
- defaultScript = file->readInt();
- defaultLibrary = file->readInt();
- icon = file->readInt();
- int itemCount = file->readInt();
-
- // Check validity (1)
- if ((!id) || (itemCount < 0) || (icon < 0) || (icon > 36) ||
- ((sorted != 0) && (sorted != 1)) ||
- ((defaultFont != 0) && (defaultFont != 1)) ||
- ((defaultTileSet != 0) && (defaultTileSet != 1)) ||
- ((defaultScene != 0) && (defaultScene != 1)) ||
- ((defaultAnimGroup != 0) && (defaultAnimGroup != 1)) ||
- ((defaultScript != 0) && (defaultScript != 1)) ||
- ((defaultLibrary != 0) && (defaultLibrary != 1))) {
- throw FileException("Corrupted folder header");
- }
-
- // Read items
- for (; itemCount > 0; --itemCount) {
- FolderItem work;
- work.itemBlockType = file->readInt();
- work.itemId = file->readInt();
- work.item = getWorldEdit()->findItem(work.itemBlockType, work.itemId);
-
- // Check validity (2)
- // Catches errors in type or id
- if (work.item == NULL) {
- throw FileException("Corrupted folder header");
- }
-
- items.push_back(work);
- }
- }
- void FolderEdit::loadContent(FileRead* file) { start_func
- delete cacheFile;
- cacheFile = file;
- cached = 1;
- }
- int FolderEdit::isContentCached() const { start_func
- return cached;
- }
- int FolderEdit::markLock() throw_File { start_func
- cacheLoad();
- return ++lockCount;
- }
- int FolderEdit::markUnlock() { start_func
- --lockCount;
- assert(lockCount >= 0);
- if ((lockCount == 0) && (cacheFile)) {
- // Recache ourselves
- cached = 1;
- }
- return lockCount;
- }
- int FolderEdit::isLocked() const { start_func
- return lockCount;
- }
- void FolderEdit::disassociate() throw_File { start_func
- // Ensure not cached- our exception point
- cacheLoad();
-
- // Drop browser node
- dropBrowser();
-
- // Notify objects
- desktop->broadcastObjChange(OBJ_FOLDER | OBJMOD_DELETE, this, 0, 0);
-
- disassociated = 1;
- }
- void FolderEdit::reassociate(TreeView* node) { start_func
- assert(disassociated);
-
- // Notify objects
- desktop->broadcastObjChange(OBJ_FOLDER | OBJMOD_CREATE, this, 0, 0);
-
- // Browser node
- addToBrowser(node, 0);
- // Ensure written to file
- headerModified = contentModified = 1;
- disassociated = 0;
- }
- void FolderEdit::setHeaderModified() { start_func
- if (!headerModified) headerModified = 1;
- }
- void FolderEdit::setContentModified() { start_func
- if (!contentModified) {
- contentModified = 1;
- // No possibility of returning to cache
- delete cacheFile;
- cacheFile = NULL;
- }
- }
- void FolderEdit::dropBrowser() { start_func
- browserNode = NULL;
- }
- void FolderEdit::addToBrowser(TreeView* node, int makeCurrent) { start_func
- browserNode = new TreeView(name, this, 0, treeviewEventWrap);
- browserNode->setIcon(icon + 1, icon);
- node->insert(browserNode, makeCurrent);
- // @TODO: Add subitems
- }
- int FolderEdit::treeviewEvent(int code, int command, int check) { start_func
- if (check) {
- if (command == EDIT_DELETE) return Window::COMMAND_ENABLE;
- return Window::COMMAND_HIDE;
- }
- switch (command) {
- case LV_RCLICK:
- // @TODO: Should actually be a popup with this as an item
- propertiesDialog(desktop->findPreviousFocusWindow());
- return 1;
-
- case EDIT_DELETE:
- case LV_DELETE:
- // Handles any error conditions/cancellation for us
- getWorldEdit()->deleteFolder(this, desktop->findPreviousFocusWindow());
- return 1;
- }
-
- return 0;
- }
- int FolderEdit::treeviewEventWrap(void* ptr, int code, int command, int check) { start_func
- return ((FolderEdit*)ptr)->treeviewEvent(code, command, check);
- }
- void FolderEdit::setName(const string& newName, Window* srcWin, Window* exWin) throw_Undo { start_func
- if (name != newName) {
- setHeaderModified();
- if (world) {
- getWorldEdit()->undo.storeUndoName(UndoBuffer::UNDO_FOLDERNAME, id, name, newName, srcWin);
- getWorldEdit()->deindexFolder(this);
- }
- name = newName;
- if (world) getWorldEdit()->indexFolder(this);
- if (browserNode) browserNode->changeName(newName);
-
- desktop->broadcastObjChange(OBJ_FOLDER | OBJMOD_NAME, this, 0, 0, exWin);
- }
- }
- void FolderEdit::addItem(SaveLoad* item, int index, Window* srcWin, Window* exWin) throw_Undo { start_func
- assert(item);
-
- FolderItem work;
- work.itemBlockType = item->getBlockType();
- work.itemId = item->getId();
- work.item = item;
- assert((work.itemBlockType == BLOCKTYPE_TILESET) ||
- (work.itemBlockType == BLOCKTYPE_SCENE) ||
- (work.itemBlockType == BLOCKTYPE_ANIMGROUP) ||
- (work.itemBlockType == BLOCKTYPE_SCRIPT) ||
- (work.itemBlockType == BLOCKTYPE_FOLDER));
- assert(work.itemId);
-
- #ifndef NDEBUG
- // Assert item isn't in list already
- vector<FolderItem>::iterator pos;
- vector<FolderItem>::iterator end = items.end();
- for (pos = items.begin(); pos != end; ++pos) {
- assert((*pos).itemBlockType != work.itemBlockType) || ((*pos).itemId != work.itemId));
- }
- #endif
- // Out of range -or- default = last position (@TODO: sorted)
- if ((index < 0) || (index > (int)items.size()))
- index = items.size();
- setHeaderModified();
- if (world) {
- getWorldEdit()->undo.storeUndoFolderAdd(id, item, index, srcWin);
- }
- // Add to list
- // @TODO: insert at 'index' (right now we assume at end, which is safe... right now.)
- items.push_back(work);
- desktop->broadcastObjChange(OBJ_FOLDER | OBJMOD_CONTENT, this, 0, 0, exWin);
- // @TODO: Update browser node
- }
- void FolderEdit::removeItem(SaveLoad* item, Window* srcWin, Window* exWin) throw_Undo { start_func
- assert(item);
-
- vector<FolderItem>::iterator pos;
- vector<FolderItem>::iterator end = items.end();
- int index = 0;
- for (pos = items.begin(); pos != end; ++pos, ++index) {
- if ((*pos).item == item) {
- setHeaderModified();
- if (world) {
- getWorldEdit()->undo.storeUndoFolderRemove(id, item, index, srcWin);
- }
-
- items.erase(pos);
- desktop->broadcastObjChange(OBJ_FOLDER | OBJMOD_CONTENT, this, 0, 0, exWin);
- // @TODO: update browser node
- return;
- }
- }
-
- assert(0);
- }
- int FolderEdit::propertiesDialog(Window* srcWin, Window* exWin) { start_func
- string newName = name;
- if (1) { // @TODO: if (FolderPropertiesDialog::create()->run(&newName, this)) {
- try {
- markLock();
- }
- catch (FileException& e) {
- guiErrorBox(string(e.details), errorTitleFile);
- return 0;
- }
- try {
- getWorldEdit()->undo.preUndoBlock();
- setName(newName, srcWin, exWin);
- getWorldEdit()->undo.postUndoBlock();
- }
- catch (UndoException& e) {
- markUnlock();
- return 0;
- }
- markUnlock();
- return 1;
- }
-
- return 0;
- }
- int FolderEdit::isHeaderModified() const { start_func
- return headerModified;
- }
- int FolderEdit::isContentModified() const { start_func
- return contentModified;
- }
- Uint32 FolderEdit::saveHeader(FileWrite* file) throw_File { start_func
- file->writeStr(name);
- file->writeInt(id);
- file->writeInt(sorted);
- file->writeInt(defaultFont);
- file->writeInt(defaultTileSet);
- file->writeInt(defaultScene);
- file->writeInt(defaultAnimGroup);
- file->writeInt(defaultScript);
- file->writeInt(defaultLibrary);
- file->writeInt(icon);
- file->writeInt(items.size());
-
- // Write items
- vector<FolderItem>::iterator pos;
- vector<FolderItem>::iterator end = items.end();
- for (pos = items.begin(); pos != end; ++pos) {
- file->writeInt((*pos).itemBlockType);
- file->writeInt((*pos).itemId);
- }
-
- return 1;
- }
- void FolderEdit::saveContent(FileWrite* file) throw_File { start_func
- }
- void FolderEdit::saveSuccess() { start_func
- headerModified = 0;
- contentModified = 0;
- }
- void FolderEdit::cachedContent(FileRead* file, int oldData) { start_func
- // If already cached..
- if (cached) {
- delete cacheFile;
- cacheFile = file;
- }
- else if (oldData) {
- delete file;
- }
- else {
- // Cache ourselves?
- if (!lockCount) {
- delete cacheFile;
- cacheFile = file;
- cached = 1;
- }
- else {
- delete file;
- }
- }
- }
|