| @@ -159,6 +159,8 @@ public: | |||||
| } | } | ||||
| virtual void doExtraInitialisation() {} | virtual void doExtraInitialisation() {} | ||||
| virtual void projectOpened (Project*) {} | |||||
| virtual void projectClosed (Project*) {} | |||||
| static JucerApplication* getApp() | static JucerApplication* getApp() | ||||
| { | { | ||||
| @@ -27,80 +27,9 @@ | |||||
| #include "jucer_FilePreviewComponent.h" | #include "jucer_FilePreviewComponent.h" | ||||
| #include "../Code Editor/jucer_SourceCodeEditor.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 | class UnknownDocument : public OpenDocumentManager::Document | ||||
| @@ -28,7 +28,6 @@ | |||||
| #include "../Project/jucer_Project.h" | #include "../Project/jucer_Project.h" | ||||
| //============================================================================== | //============================================================================== | ||||
| /** | /** | ||||
| */ | */ | ||||
| @@ -120,5 +119,78 @@ private: | |||||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenDocumentManager); | 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__ | #endif // __JUCER_OPENDOCUMENTMANAGER_JUCEHEADER__ | ||||
| @@ -57,16 +57,20 @@ void SourceCodeEditor::resized() | |||||
| editor.setBounds (getLocalBounds()); | 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; | 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, | static SourceCodeEditor* createFor (OpenDocumentManager::Document* document, | ||||
| CodeDocument& codeDocument); | CodeDocument& codeDocument); | ||||
| static CodeTokeniser* getTokeniserFor (const File& file); | |||||
| //============================================================================== | //============================================================================== | ||||
| void resized(); | void resized(); | ||||
| @@ -28,6 +28,7 @@ | |||||
| #include "../Project Saving/jucer_ProjectExporter.h" | #include "../Project Saving/jucer_ProjectExporter.h" | ||||
| #include "../Project Saving/jucer_ProjectSaver.h" | #include "../Project Saving/jucer_ProjectSaver.h" | ||||
| #include "../Application/jucer_OpenDocumentManager.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)); | mainProjectIcon.setImage (ImageCache::getFromMemory (BinaryData::juce_icon_png, BinaryData::juce_icon_pngSize)); | ||||
| projectRoot.addListener (this); | projectRoot.addListener (this); | ||||
| JucerApplication::getApp()->projectOpened (this); | |||||
| } | } | ||||
| Project::~Project() | Project::~Project() | ||||
| { | { | ||||
| JucerApplication::getApp()->projectClosed (this); | |||||
| projectRoot.removeListener (this); | projectRoot.removeListener (this); | ||||
| OpenDocumentManager::getInstance()->closeAllDocumentsUsingProject (*this, false); | 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!"); | return Result::fail ("The document contains errors and couldn't be parsed!"); | ||||
| registerRecentFile (file); | registerRecentFile (file); | ||||
| JucerApplication::getApp()->projectClosed (this); | |||||
| projectRoot = newTree; | projectRoot = newTree; | ||||
| JucerApplication::getApp()->projectOpened (this); | |||||
| removeDefunctExporters(); | removeDefunctExporters(); | ||||
| setMissingDefaultValues(); | setMissingDefaultValues(); | ||||
| @@ -106,6 +106,9 @@ public: | |||||
| /** Returns the object that this pointer is managing. */ | /** Returns the object that this pointer is managing. */ | ||||
| inline operator ObjectType*() const noexcept { return object; } | 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. */ | /** Returns the object that this pointer is managing. */ | ||||
| inline ObjectType& operator*() const noexcept { return *object; } | inline ObjectType& operator*() const noexcept { return *object; } | ||||
| @@ -127,6 +130,24 @@ public: | |||||
| object.release(); | 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 | /** Returns true if the target object will be deleted when this pointer | ||||
| object is deleted. | object is deleted. | ||||
| */ | */ | ||||