| @@ -159,6 +159,8 @@ public: | |||
| } | |||
| virtual void doExtraInitialisation() {} | |||
| virtual void projectOpened (Project*) {} | |||
| virtual void projectClosed (Project*) {} | |||
| static JucerApplication* getApp() | |||
| { | |||
| @@ -27,80 +27,9 @@ | |||
| #include "jucer_FilePreviewComponent.h" | |||
| #include "../Code Editor/jucer_SourceCodeEditor.h" | |||
| //============================================================================== | |||
| class SourceCodeDocument : public OpenDocumentManager::Document | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| SourceCodeDocument (Project* project_, const File& file_) | |||
| : modDetector (file_), project (project_) | |||
| { | |||
| codeDoc = new CodeDocument(); | |||
| reloadFromFile(); | |||
| } | |||
| //============================================================================== | |||
| struct Type : public OpenDocumentManager::DocumentType | |||
| { | |||
| bool canOpenFile (const File& file) { return file.hasFileExtension ("cpp;h;hpp;mm;m;c;cc;cxx;txt;xml;plist;rtf;html;htm;php;py;rb;cs"); } | |||
| Document* openFile (Project* project, const File& file) { return new SourceCodeDocument (project, file); } | |||
| }; | |||
| //============================================================================== | |||
| bool loadedOk() const { return true; } | |||
| bool isForFile (const File& file) const { return getFile() == file; } | |||
| bool isForNode (const ValueTree& node) const { return false; } | |||
| bool refersToProject (Project& p) const { return project == &p; } | |||
| Project* getProject() const { return project; } | |||
| bool canSaveAs() const { return true; } | |||
| String getName() const { return getFile().getFileName(); } | |||
| String getType() const { return getFile().getFileExtension() + " file"; } | |||
| File getFile() const { return modDetector.getFile(); } | |||
| bool needsSaving() const { return codeDoc != nullptr && codeDoc->hasChangedSinceSavePoint(); } | |||
| bool hasFileBeenModifiedExternally() { return modDetector.hasBeenModified(); } | |||
| void fileHasBeenRenamed (const File& newFile) { modDetector.fileHasBeenRenamed (newFile); } | |||
| void reloadFromFile() | |||
| { | |||
| modDetector.updateHash(); | |||
| ScopedPointer <InputStream> in (modDetector.getFile().createInputStream()); | |||
| Component* SourceCodeDocument::createEditor() { return SourceCodeEditor::createFor (this, *codeDoc); } | |||
| if (in != nullptr) | |||
| codeDoc->loadFromStream (*in); | |||
| } | |||
| bool save() | |||
| { | |||
| TemporaryFile temp (modDetector.getFile()); | |||
| ScopedPointer <FileOutputStream> out (temp.getFile().createOutputStream()); | |||
| if (out == nullptr || ! codeDoc->writeToStream (*out)) | |||
| return false; | |||
| out = nullptr; | |||
| if (! temp.overwriteTargetFileWithTemporary()) | |||
| return false; | |||
| modDetector.updateHash(); | |||
| return true; | |||
| } | |||
| bool saveAs() | |||
| { | |||
| jassertfalse; //xxx todo | |||
| return false; | |||
| } | |||
| Component* createEditor() { return SourceCodeEditor::createFor (this, *codeDoc); } | |||
| Component* createViewer() { return createEditor(); } | |||
| private: | |||
| FileModificationDetector modDetector; | |||
| ScopedPointer <CodeDocument> codeDoc; | |||
| Project* project; | |||
| }; | |||
| //============================================================================== | |||
| class UnknownDocument : public OpenDocumentManager::Document | |||
| @@ -28,7 +28,6 @@ | |||
| #include "../Project/jucer_Project.h" | |||
| //============================================================================== | |||
| /** | |||
| */ | |||
| @@ -120,5 +119,78 @@ private: | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenDocumentManager); | |||
| }; | |||
| //============================================================================== | |||
| class SourceCodeDocument : public OpenDocumentManager::Document | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| SourceCodeDocument (Project* project_, const File& file_) | |||
| : modDetector (file_), project (project_) | |||
| { | |||
| codeDoc = new CodeDocument(); | |||
| reloadFromFile(); | |||
| } | |||
| //============================================================================== | |||
| struct Type : public OpenDocumentManager::DocumentType | |||
| { | |||
| bool canOpenFile (const File& file) { return file.hasFileExtension ("cpp;h;hpp;mm;m;c;cc;cxx;txt;xml;plist;rtf;html;htm;php;py;rb;cs"); } | |||
| Document* openFile (Project* project, const File& file) { return new SourceCodeDocument (project, file); } | |||
| }; | |||
| //============================================================================== | |||
| bool loadedOk() const { return true; } | |||
| bool isForFile (const File& file) const { return getFile() == file; } | |||
| bool isForNode (const ValueTree& node) const { return false; } | |||
| bool refersToProject (Project& p) const { return project == &p; } | |||
| Project* getProject() const { return project; } | |||
| bool canSaveAs() const { return true; } | |||
| String getName() const { return getFile().getFileName(); } | |||
| String getType() const { return getFile().getFileExtension() + " file"; } | |||
| File getFile() const { return modDetector.getFile(); } | |||
| bool needsSaving() const { return codeDoc != nullptr && codeDoc->hasChangedSinceSavePoint(); } | |||
| bool hasFileBeenModifiedExternally() { return modDetector.hasBeenModified(); } | |||
| void fileHasBeenRenamed (const File& newFile) { modDetector.fileHasBeenRenamed (newFile); } | |||
| void reloadFromFile() | |||
| { | |||
| modDetector.updateHash(); | |||
| ScopedPointer <InputStream> in (modDetector.getFile().createInputStream()); | |||
| if (in != nullptr) | |||
| codeDoc->loadFromStream (*in); | |||
| } | |||
| bool save() | |||
| { | |||
| TemporaryFile temp (modDetector.getFile()); | |||
| ScopedPointer <FileOutputStream> out (temp.getFile().createOutputStream()); | |||
| if (out == nullptr || ! codeDoc->writeToStream (*out)) | |||
| return false; | |||
| out = nullptr; | |||
| if (! temp.overwriteTargetFileWithTemporary()) | |||
| return false; | |||
| modDetector.updateHash(); | |||
| return true; | |||
| } | |||
| bool saveAs() | |||
| { | |||
| jassertfalse; //xxx todo | |||
| return false; | |||
| } | |||
| Component* createEditor(); | |||
| Component* createViewer() { return createEditor(); } | |||
| protected: | |||
| FileModificationDetector modDetector; | |||
| ScopedPointer <CodeDocument> codeDoc; | |||
| Project* project; | |||
| }; | |||
| #endif // __JUCER_OPENDOCUMENTMANAGER_JUCEHEADER__ | |||
| @@ -57,16 +57,20 @@ void SourceCodeEditor::resized() | |||
| editor.setBounds (getLocalBounds()); | |||
| } | |||
| SourceCodeEditor* SourceCodeEditor::createFor (OpenDocumentManager::Document* document, | |||
| CodeDocument& codeDocument) | |||
| CodeTokeniser* SourceCodeEditor::getTokeniserFor (const File& file) | |||
| { | |||
| CodeTokeniser* tokeniser = nullptr; | |||
| if (document->getFile().hasFileExtension (sourceOrHeaderFileExtensions)) | |||
| if (file.hasFileExtension (sourceOrHeaderFileExtensions)) | |||
| { | |||
| static CPlusPlusCodeTokeniser cppTokeniser; | |||
| tokeniser = &cppTokeniser; | |||
| return &cppTokeniser; | |||
| } | |||
| return new SourceCodeEditor (document, codeDocument, tokeniser); | |||
| return nullptr; | |||
| } | |||
| SourceCodeEditor* SourceCodeEditor::createFor (OpenDocumentManager::Document* document, | |||
| CodeDocument& codeDocument) | |||
| { | |||
| return new SourceCodeEditor (document, codeDocument, | |||
| getTokeniserFor (document->getFile())); | |||
| } | |||
| @@ -46,6 +46,8 @@ public: | |||
| static SourceCodeEditor* createFor (OpenDocumentManager::Document* document, | |||
| CodeDocument& codeDocument); | |||
| static CodeTokeniser* getTokeniserFor (const File& file); | |||
| //============================================================================== | |||
| void resized(); | |||
| @@ -28,6 +28,7 @@ | |||
| #include "../Project Saving/jucer_ProjectExporter.h" | |||
| #include "../Project Saving/jucer_ProjectSaver.h" | |||
| #include "../Application/jucer_OpenDocumentManager.h" | |||
| #include "../Application/jucer_Application.h" | |||
| //============================================================================== | |||
| @@ -62,10 +63,14 @@ Project::Project (const File& file_) | |||
| mainProjectIcon.setImage (ImageCache::getFromMemory (BinaryData::juce_icon_png, BinaryData::juce_icon_pngSize)); | |||
| projectRoot.addListener (this); | |||
| JucerApplication::getApp()->projectOpened (this); | |||
| } | |||
| Project::~Project() | |||
| { | |||
| JucerApplication::getApp()->projectClosed (this); | |||
| projectRoot.removeListener (this); | |||
| OpenDocumentManager::getInstance()->closeAllDocumentsUsingProject (*this, false); | |||
| } | |||
| @@ -228,7 +233,9 @@ Result Project::loadDocument (const File& file) | |||
| return Result::fail ("The document contains errors and couldn't be parsed!"); | |||
| registerRecentFile (file); | |||
| JucerApplication::getApp()->projectClosed (this); | |||
| projectRoot = newTree; | |||
| JucerApplication::getApp()->projectOpened (this); | |||
| removeDefunctExporters(); | |||
| setMissingDefaultValues(); | |||
| @@ -106,6 +106,9 @@ public: | |||
| /** Returns the object that this pointer is managing. */ | |||
| inline operator ObjectType*() const noexcept { return object; } | |||
| /** Returns the object that this pointer is managing. */ | |||
| inline ObjectType* get() const noexcept { return object; } | |||
| /** Returns the object that this pointer is managing. */ | |||
| inline ObjectType& operator*() const noexcept { return *object; } | |||
| @@ -127,6 +130,24 @@ public: | |||
| object.release(); | |||
| } | |||
| /** Makes this OptionalScopedPointer point at a new object, specifying whether the | |||
| OptionalScopedPointer will take ownership of the object. | |||
| If takeOwnership is true, then the OptionalScopedPointer will act like a ScopedPointer, | |||
| deleting the object when it is itself deleted. If this parameter is false, then the | |||
| OptionalScopedPointer just holds a normal pointer to the object, and won't delete it. | |||
| */ | |||
| void set (ObjectType* newObject, bool takeOwnership) | |||
| { | |||
| if (object != newObject) | |||
| { | |||
| clear(); | |||
| object = newObject; | |||
| } | |||
| shouldDelete = takeOwnership; | |||
| } | |||
| /** Returns true if the target object will be deleted when this pointer | |||
| object is deleted. | |||
| */ | |||