1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-02-09 04:30:09 +00:00
JUCE/extras/Jucer (experimental)/Source/ui/jucer_OpenDocumentManager.cpp
2010-04-27 19:19:18 +01:00

450 lines
14 KiB
C++

/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-10 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_SourceCodeEditor.h"
#include "Drawable Editor/jucer_DrawableEditor.h"
#include "jucer_ItemPreviewComponent.h"
#include "Component Editor/jucer_ComponentEditor.h"
//==============================================================================
class SourceCodeDocument : public OpenDocumentManager::Document
{
public:
SourceCodeDocument (const File& file_)
: modDetector (file_)
{
codeDoc = new CodeDocument();
reloadFromFile();
}
~SourceCodeDocument()
{
}
bool loadedOk() const { return true; }
bool isForFile (const File& file) const { return modDetector.getFile() == file; }
bool isForNode (const ValueTree& node) const { return false; }
bool refersToProject (Project& project) const { return false; }
const String getName() const { return modDetector.getFile().getFileName(); }
const String getType() const { return modDetector.getFile().getFileExtension() + " file"; }
bool needsSaving() const { return codeDoc != 0 && codeDoc->hasChangedSinceSavePoint(); }
bool hasFileBeenModifiedExternally() { return modDetector.hasBeenModified(); }
void reloadFromFile()
{
modDetector.updateHash();
ScopedPointer <InputStream> in (modDetector.getFile().createInputStream());
if (in != 0)
codeDoc->loadFromStream (*in);
}
bool save()
{
TemporaryFile temp (modDetector.getFile());
ScopedPointer <FileOutputStream> out (temp.getFile().createOutputStream());
if (out == 0 || ! codeDoc->writeToStream (*out))
return false;
out = 0;
return temp.overwriteTargetFileWithTemporary();
}
Component* createEditor()
{
CodeTokeniser* tokeniser = 0;
if (SourceCodeEditor::isCppFile (modDetector.getFile()))
tokeniser = &cppTokeniser;
return new SourceCodeEditor (this, *codeDoc, tokeniser);
}
private:
FileModificationDetector modDetector;
ScopedPointer <CodeDocument> codeDoc;
CPlusPlusCodeTokeniser cppTokeniser;
};
//==============================================================================
class ComponentDocumentType : public OpenDocumentManager::Document
{
public:
ComponentDocumentType (Project* project_, const File& file_)
: project (project_),
modDetector (file_)
{
reloadFromFile();
}
~ComponentDocumentType()
{
componentDoc = 0;
}
static bool isComponentFile (const File& file) { return ComponentDocument::isComponentFile (file); }
bool loadedOk() const { return componentDoc != 0; }
bool isForFile (const File& file) const { return modDetector.getFile() == file; }
bool isForNode (const ValueTree& node) const { return false; }
bool refersToProject (Project& p) const { return project == &p; }
const String getType() const { return "Jucer Component"; }
const String getName() const { return modDetector.getFile().getFileName(); }
bool needsSaving() const { return componentDoc != 0 && componentDoc->hasChangedSinceLastSave(); }
bool hasFileBeenModifiedExternally() { return modDetector.hasBeenModified(); }
void reloadFromFile()
{
modDetector.updateHash();
if (componentDoc == 0)
componentDoc = new ComponentDocument (project, modDetector.getFile());
if (! componentDoc->reload())
componentDoc = 0;
}
bool save()
{
return componentDoc->save();
}
Component* createEditor()
{
if (componentDoc == 0)
{
jassertfalse;
return 0;
}
return new ComponentEditor (this, project, componentDoc);
}
private:
Project* project;
FileModificationDetector modDetector;
ScopedPointer <ComponentDocument> componentDoc;
};
//==============================================================================
class DrawableDocumentType : public OpenDocumentManager::Document
{
public:
DrawableDocumentType (Project* project_, const File& file_)
: project (project_),
modDetector (file_)
{
reloadFromFile();
}
~DrawableDocumentType()
{
drawableDoc = 0;
}
static bool isDrawableFile (const File& file) { return file.hasFileExtension (".drawable"); }
bool loadedOk() const { return drawableDoc != 0; }
bool isForFile (const File& file) const { return modDetector.getFile() == file; }
bool isForNode (const ValueTree& node) const { return false; }
bool refersToProject (Project& p) const { return project == &p; }
const String getType() const { return "Drawable"; }
const String getName() const { return modDetector.getFile().getFileName(); }
bool needsSaving() const { return drawableDoc != 0 && drawableDoc->hasChangedSinceLastSave(); }
bool hasFileBeenModifiedExternally() { return modDetector.hasBeenModified(); }
void reloadFromFile()
{
modDetector.updateHash();
if (drawableDoc == 0)
drawableDoc = new DrawableDocument (project, modDetector.getFile());
if (! drawableDoc->reload())
drawableDoc = 0;
}
bool save()
{
return drawableDoc->save();
}
Component* createEditor()
{
jassert (drawableDoc != 0);
if (drawableDoc == 0)
return 0;
return new DrawableEditor (this, project, drawableDoc);
}
private:
Project* project;
FileModificationDetector modDetector;
ScopedPointer <DrawableDocument> drawableDoc;
};
//==============================================================================
class UnknownDocument : public OpenDocumentManager::Document
{
public:
UnknownDocument (Project* project_, const File& file_)
: project (project_), file (file_)
{
reloadFromFile();
}
~UnknownDocument() {}
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; }
bool needsSaving() const { return false; }
bool save() { return true; }
bool hasFileBeenModifiedExternally() { return fileModificationTime != file.getLastModificationTime(); }
void reloadFromFile() { fileModificationTime = file.getLastModificationTime(); }
const String getName() const { return file.getFileName(); }
Component* createEditor() { return new ItemPreviewComponent (file); }
const String getType() const
{
if (file.getFileExtension().isNotEmpty())
return file.getFileExtension() + " file";
jassertfalse
return "Unknown";
}
private:
Project* const project;
const File file;
Time fileModificationTime;
UnknownDocument (const UnknownDocument&);
UnknownDocument& operator= (const UnknownDocument&);
};
//==============================================================================
OpenDocumentManager::OpenDocumentManager()
{
}
OpenDocumentManager::~OpenDocumentManager()
{
clearSingletonInstance();
}
juce_ImplementSingleton_SingleThreaded (OpenDocumentManager);
//==============================================================================
void OpenDocumentManager::registerEditor (DocumentEditorComponent* editor)
{
editors.add (editor);
}
void OpenDocumentManager::deregisterEditor (DocumentEditorComponent* editor)
{
editors.removeValue (editor);
}
//==============================================================================
bool OpenDocumentManager::canOpenFile (const File& file)
{
return DrawableDocumentType::isDrawableFile (file)
|| SourceCodeEditor::isTextFile (file);
}
OpenDocumentManager::Document* OpenDocumentManager::getDocumentForFile (Project* project, const File& file)
{
for (int i = documents.size(); --i >= 0;)
if (documents.getUnchecked(i)->isForFile (file))
return documents.getUnchecked(i);
Document* d = 0;
if (ComponentDocumentType::isComponentFile (file))
d = new ComponentDocumentType (project, file);
else if (DrawableDocumentType::isDrawableFile (file))
d = new DrawableDocumentType (project, file);
else if (SourceCodeEditor::isTextFile (file))
d = new SourceCodeDocument (file);
else
d = new UnknownDocument (project, file);
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);
}
void OpenDocumentManager::moveDocumentToTopOfStack (Document* doc)
{
for (int i = documents.size(); --i >= 0;)
{
if (doc == documents.getUnchecked(i))
{
documents.move (i, 0);
commandManager->commandStatusChanged();
break;
}
}
}
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 != 0)
{
if (saveIfNeeded)
{
if (saveIfNeededAndUserAgrees (doc) != FileBasedDocument::savedOk)
return false;
}
for (int i = editors.size(); --i >= 0;)
if (editors.getUnchecked(i)->getDocument() == doc)
editors.getUnchecked(i)->deleteSelf();
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::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();
}
}