| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library - "Jules' Utility Class Extensions"
 -    Copyright 2004-11 by Raw Material Software Ltd.
 - 
 -   ------------------------------------------------------------------------------
 - 
 -    JUCE can be redistributed and/or modified under the terms of the GNU General
 -    Public License (Version 2), as published by the Free Software Foundation.
 -    A copy of the license is included in the JUCE distribution, or can be found
 -    online at www.gnu.org/licenses.
 - 
 -    JUCE 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.
 - 
 -   ------------------------------------------------------------------------------
 - 
 -    To release a closed-source product which uses JUCE, commercial licenses are
 -    available: visit www.rawmaterialsoftware.com/juce for more information.
 - 
 -   ==============================================================================
 - */
 - 
 - #include "jucer_OpenDocumentManager.h"
 - #include "jucer_FilePreviewComponent.h"
 - #include "../Code Editor/jucer_SourceCodeEditor.h"
 - #include "jucer_Application.h"
 - 
 - 
 - //==============================================================================
 - class UnknownDocument  : public OpenDocumentManager::Document
 - {
 - public:
 -     UnknownDocument (Project* project_, const File& file_)
 -        : project (project_), file (file_)
 -     {
 -         reloadFromFile();
 -     }
 - 
 -     //==============================================================================
 -     struct Type  : public OpenDocumentManager::DocumentType
 -     {
 -         bool canOpenFile (const File&)                              { return true; }
 -         Document* openFile (Project* project, const File& file)     { return new UnknownDocument (project, file); }
 -     };
 - 
 -     //==============================================================================
 -     bool loadedOk() const                           { return true; }
 -     bool isForFile (const File& file_) const        { return file == file_; }
 -     bool isForNode (const ValueTree& node_) const   { return false; }
 -     bool refersToProject (Project& p) const         { return project == &p; }
 -     Project* getProject() const                     { return project; }
 -     bool needsSaving() const                        { return false; }
 -     bool save()                                     { return true; }
 -     bool hasFileBeenModifiedExternally()            { return fileModificationTime != file.getLastModificationTime(); }
 -     void reloadFromFile()                           { fileModificationTime = file.getLastModificationTime(); }
 -     String getName() const                          { return file.getFileName(); }
 -     File getFile() const                            { return file; }
 -     Component* createEditor()                       { return new ItemPreviewComponent (file); }
 -     Component* createViewer()                       { return createEditor(); }
 -     void fileHasBeenRenamed (const File& newFile)   { file = newFile; }
 -     String getState() const                         { return String::empty; }
 -     void restoreState (const String& state)         {}
 - 
 -     String getType() const
 -     {
 -         if (file.getFileExtension().isNotEmpty())
 -             return file.getFileExtension() + " file";
 - 
 -         jassertfalse
 -         return "Unknown";
 -     }
 - 
 - private:
 -     Project* const project;
 -     File file;
 -     Time fileModificationTime;
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (UnknownDocument);
 - };
 - 
 - 
 - //==============================================================================
 - OpenDocumentManager::OpenDocumentManager()
 - {
 -     registerType (new UnknownDocument::Type());
 -     registerType (new SourceCodeDocument::Type());
 - }
 - 
 - OpenDocumentManager::~OpenDocumentManager()
 - {
 - }
 - 
 - void OpenDocumentManager::clear()
 - {
 -     documents.clear();
 -     types.clear();
 - }
 - 
 - //==============================================================================
 - void OpenDocumentManager::registerType (DocumentType* type)
 - {
 -     types.add (type);
 - }
 - 
 - //==============================================================================
 - void OpenDocumentManager::addListener (DocumentCloseListener* listener)
 - {
 -     listeners.addIfNotAlreadyThere (listener);
 - }
 - 
 - void OpenDocumentManager::removeListener (DocumentCloseListener* listener)
 - {
 -     listeners.removeFirstMatchingValue (listener);
 - }
 - 
 - //==============================================================================
 - bool OpenDocumentManager::canOpenFile (const File& file)
 - {
 -     for (int i = types.size(); --i >= 0;)
 -         if (types.getUnchecked(i)->canOpenFile (file))
 -             return true;
 - 
 -     return false;
 - }
 - 
 - OpenDocumentManager::Document* OpenDocumentManager::openFile (Project* project, const File& file)
 - {
 -     for (int i = documents.size(); --i >= 0;)
 -         if (documents.getUnchecked(i)->isForFile (file))
 -             return documents.getUnchecked(i);
 - 
 -     Document* d = nullptr;
 - 
 -     for (int i = types.size(); --i >= 0 && d == nullptr;)
 -     {
 -         if (types.getUnchecked(i)->canOpenFile (file))
 -         {
 -             d = types.getUnchecked(i)->openFile (project, file);
 -             jassert (d != nullptr);
 -         }
 -     }
 - 
 -     jassert (d != nullptr);  // should always at least have been picked up by UnknownDocument
 - 
 -     documents.add (d);
 -     commandManager->commandStatusChanged();
 -     return d;
 - }
 - 
 - int OpenDocumentManager::getNumOpenDocuments() const
 - {
 -     return documents.size();
 - }
 - 
 - OpenDocumentManager::Document* OpenDocumentManager::getOpenDocument (int index) const
 - {
 -     return documents.getUnchecked (index);
 - }
 - 
 - FileBasedDocument::SaveResult OpenDocumentManager::saveIfNeededAndUserAgrees (OpenDocumentManager::Document* doc)
 - {
 -     if (! doc->needsSaving())
 -         return FileBasedDocument::savedOk;
 - 
 -     const int r = AlertWindow::showYesNoCancelBox (AlertWindow::QuestionIcon,
 -                                                    TRANS("Closing document..."),
 -                                                    TRANS("Do you want to save the changes to \"")
 -                                                        + doc->getName() + "\"?",
 -                                                    TRANS("save"),
 -                                                    TRANS("discard changes"),
 -                                                    TRANS("cancel"));
 - 
 -     if (r == 1)
 -     {
 -         // save changes
 -         return doc->save() ? FileBasedDocument::savedOk
 -                            : FileBasedDocument::failedToWriteToFile;
 -     }
 -     else if (r == 2)
 -     {
 -         // discard changes
 -         return FileBasedDocument::savedOk;
 -     }
 - 
 -     return FileBasedDocument::userCancelledSave;
 - }
 - 
 - 
 - bool OpenDocumentManager::closeDocument (int index, bool saveIfNeeded)
 - {
 -     Document* doc = documents [index];
 - 
 -     if (doc != nullptr)
 -     {
 -         if (saveIfNeeded)
 -         {
 -             if (saveIfNeededAndUserAgrees (doc) != FileBasedDocument::savedOk)
 -                 return false;
 -         }
 - 
 -         for (int i = listeners.size(); --i >= 0;)
 -             listeners.getUnchecked(i)->documentAboutToClose (doc);
 - 
 -         documents.remove (index);
 -         commandManager->commandStatusChanged();
 -     }
 - 
 -     return true;
 - }
 - 
 - bool OpenDocumentManager::closeDocument (Document* document, bool saveIfNeeded)
 - {
 -     return closeDocument (documents.indexOf (document), saveIfNeeded);
 - }
 - 
 - void OpenDocumentManager::closeFile (const File& f, bool saveIfNeeded)
 - {
 -     for (int i = documents.size(); --i >= 0;)
 -     {
 -         Document* d = documents.getUnchecked (i);
 - 
 -         if (d->isForFile (f))
 -             closeDocument (i, saveIfNeeded);
 -     }
 - }
 - 
 - bool OpenDocumentManager::closeAll (bool askUserToSave)
 - {
 -     for (int i = getNumOpenDocuments(); --i >= 0;)
 -         if (! closeDocument (i, askUserToSave))
 -             return false;
 - 
 -     return true;
 - }
 - 
 - bool OpenDocumentManager::closeAllDocumentsUsingProject (Project& project, bool saveIfNeeded)
 - {
 -     for (int i = documents.size(); --i >= 0;)
 -     {
 -         Document* d = documents.getUnchecked (i);
 - 
 -         if (d->refersToProject (project))
 -         {
 -             if (! closeDocument (i, saveIfNeeded))
 -                 return false;
 -         }
 -     }
 - 
 -     return true;
 - }
 - 
 - bool OpenDocumentManager::anyFilesNeedSaving() const
 - {
 -     for (int i = documents.size(); --i >= 0;)
 -     {
 -         Document* d = documents.getUnchecked (i);
 - 
 -         if (d->needsSaving())
 -             return true;
 -     }
 - 
 -     return false;
 - }
 - 
 - bool OpenDocumentManager::saveAll()
 - {
 -     for (int i = documents.size(); --i >= 0;)
 -     {
 -         Document* d = documents.getUnchecked (i);
 - 
 -         if (! d->save())
 -             return false;
 -     }
 - 
 -     return true;
 - }
 - 
 - void OpenDocumentManager::reloadModifiedFiles()
 - {
 -     for (int i = documents.size(); --i >= 0;)
 -     {
 -         Document* d = documents.getUnchecked (i);
 - 
 -         if (d->hasFileBeenModifiedExternally())
 -             d->reloadFromFile();
 -     }
 - }
 - 
 - void OpenDocumentManager::fileHasBeenRenamed (const File& oldFile, const File& newFile)
 - {
 -     for (int i = documents.size(); --i >= 0;)
 -     {
 -         Document* d = documents.getUnchecked (i);
 - 
 -         if (d->isForFile (oldFile))
 -             d->fileHasBeenRenamed (newFile);
 -     }
 - }
 - 
 - 
 - //==============================================================================
 - RecentDocumentList::RecentDocumentList()
 - {
 -     JucerApplication::getApp().openDocumentManager.addListener (this);
 - }
 - 
 - RecentDocumentList::~RecentDocumentList()
 - {
 -     JucerApplication::getApp().openDocumentManager.removeListener (this);
 - }
 - 
 - void RecentDocumentList::clear()
 - {
 -     previousDocs.clear();
 -     nextDocs.clear();
 - }
 - 
 - void RecentDocumentList::newDocumentOpened (OpenDocumentManager::Document* document)
 - {
 -     if (document != nullptr && document != getCurrentDocument())
 -     {
 -         nextDocs.clear();
 -         previousDocs.add (document);
 -     }
 - }
 - 
 - bool RecentDocumentList::canGoToPrevious() const
 - {
 -     return previousDocs.size() > 1;
 - }
 - 
 - bool RecentDocumentList::canGoToNext() const
 - {
 -     return nextDocs.size() > 0;
 - }
 - 
 - OpenDocumentManager::Document* RecentDocumentList::getPrevious()
 - {
 -     if (! canGoToPrevious())
 -         return nullptr;
 - 
 -     nextDocs.insert (0, previousDocs.remove (previousDocs.size() - 1));
 -     return previousDocs.getLast();
 - }
 - 
 - OpenDocumentManager::Document* RecentDocumentList::getNext()
 - {
 -     if (! canGoToNext())
 -         return nullptr;
 - 
 -     OpenDocumentManager::Document* d = nextDocs.remove (0);
 -     previousDocs.add (d);
 -     return d;
 - }
 - 
 - OpenDocumentManager::Document* RecentDocumentList::getClosestPreviousDocOtherThan (OpenDocumentManager::Document* oneToAvoid) const
 - {
 -     for (int i = previousDocs.size(); --i >= 0;)
 -         if (previousDocs.getUnchecked(i) != oneToAvoid)
 -             return previousDocs.getUnchecked(i);
 - 
 -     return nullptr;
 - }
 - 
 - void RecentDocumentList::documentAboutToClose (OpenDocumentManager::Document* document)
 - {
 -     previousDocs.removeAllInstancesOf (document);
 -     nextDocs.removeAllInstancesOf (document);
 - 
 -     jassert (! previousDocs.contains (document));
 -     jassert (! nextDocs.contains (document));
 - }
 - 
 - static void restoreDocList (Project& project, Array <OpenDocumentManager::Document*>& list, const XmlElement* xml)
 - {
 -     if (xml != nullptr)
 -     {
 -         OpenDocumentManager& odm = JucerApplication::getApp().openDocumentManager;
 - 
 -         forEachXmlChildElementWithTagName (*xml, e, "DOC")
 -         {
 -             const File file (e->getStringAttribute ("file"));
 - 
 -             if (file.exists())
 -             {
 -                 OpenDocumentManager::Document* doc = odm.openFile (&project, file);
 - 
 -                 if (doc != nullptr)
 -                 {
 -                     doc->restoreState (e->getStringAttribute ("state"));
 - 
 -                     list.add (doc);
 -                 }
 -             }
 -         }
 -     }
 - }
 - 
 - void RecentDocumentList::restoreFromXML (Project& project, const XmlElement& xml)
 - {
 -     clear();
 - 
 -     if (xml.hasTagName ("RECENT_DOCUMENTS"))
 -     {
 -         restoreDocList (project, previousDocs, xml.getChildByName ("PREVIOUS"));
 -         restoreDocList (project, nextDocs,     xml.getChildByName ("NEXT"));
 -     }
 - }
 - 
 - static void saveDocList (const Array <OpenDocumentManager::Document*>& list, XmlElement& xml)
 - {
 -     for (int i = 0; i < list.size(); ++i)
 -     {
 -         const OpenDocumentManager::Document& doc = *list.getUnchecked(i);
 - 
 -         XmlElement* e = xml.createNewChildElement ("DOC");
 - 
 -         e->setAttribute ("file", doc.getFile().getFullPathName());
 -         e->setAttribute ("state", doc.getState());
 -     }
 - }
 - 
 - XmlElement* RecentDocumentList::createXML() const
 - {
 -     XmlElement* xml = new XmlElement ("RECENT_DOCUMENTS");
 - 
 -     saveDocList (previousDocs, *xml->createNewChildElement ("PREVIOUS"));
 -     saveDocList (nextDocs,     *xml->createNewChildElement ("NEXT"));
 - 
 -     return xml;
 - }
 
 
  |