diff --git a/extras/Projucer/Source/Application/jucer_Application.cpp b/extras/Projucer/Source/Application/jucer_Application.cpp index c606b225eb..4b9c72270e 100644 --- a/extras/Projucer/Source/Application/jucer_Application.cpp +++ b/extras/Projucer/Source/Application/jucer_Application.cpp @@ -1055,7 +1055,7 @@ bool ProjucerApplication::perform (const InvocationInfo& info) case CommandIDs::newPIP: createNewPIP(); break; case CommandIDs::open: askUserToOpenFile(); break; case CommandIDs::launchDemoRunner: launchDemoRunner(); break; - case CommandIDs::saveAll: openDocumentManager.saveAll(); break; + case CommandIDs::saveAll: saveAllDocuments(); break; case CommandIDs::closeAllWindows: closeAllMainWindowsAndQuitIfNeeded(); break; case CommandIDs::closeAllDocuments: closeAllDocuments (true); break; case CommandIDs::clearRecentFiles: clearRecentFiles(); break; @@ -1120,6 +1120,15 @@ bool ProjucerApplication::openFile (const File& file) return mainWindowList.openFile (file); } +void ProjucerApplication::saveAllDocuments() +{ + openDocumentManager.saveAll(); + + for (int i = 0; i < mainWindowList.windows.size(); ++i) + if (auto* pcc = mainWindowList.windows.getUnchecked(i)->getProjectContentComponent()) + pcc->refreshProjectTreeFileStatuses(); +} + bool ProjucerApplication::closeAllDocuments (bool askUserToSave) { return openDocumentManager.closeAll (askUserToSave); diff --git a/extras/Projucer/Source/Application/jucer_Application.h b/extras/Projucer/Source/Application/jucer_Application.h index 6689d45fa6..333e688e1b 100644 --- a/extras/Projucer/Source/Application/jucer_Application.h +++ b/extras/Projucer/Source/Application/jucer_Application.h @@ -96,6 +96,7 @@ public: void createNewPIP(); void askUserToOpenFile(); bool openFile (const File&); + void saveAllDocuments(); bool closeAllDocuments (bool askUserToSave); bool closeAllMainWindows(); void closeAllMainWindowsAndQuitIfNeeded(); diff --git a/extras/Projucer/Source/CodeEditor/jucer_DocumentEditorComponent.cpp b/extras/Projucer/Source/CodeEditor/jucer_DocumentEditorComponent.cpp index 1629e7b526..4a457565ef 100644 --- a/extras/Projucer/Source/CodeEditor/jucer_DocumentEditorComponent.cpp +++ b/extras/Projucer/Source/CodeEditor/jucer_DocumentEditorComponent.cpp @@ -47,13 +47,20 @@ bool DocumentEditorComponent::documentAboutToClose (OpenDocumentManager::Documen { jassert (document != nullptr); - if (ProjectContentComponent* pcc = findParentComponentOfClass()) + if (auto* pcc = findParentComponentOfClass()) pcc->hideDocument (document); } return true; } -void DocumentEditorComponent::setEditedState (bool /*hasBeenEdited*/) +void DocumentEditorComponent::setEditedState (bool hasBeenEdited) { + if (hasBeenEdited != lastEditedState) + { + if (auto* pcc = findParentComponentOfClass()) + pcc->refreshProjectTreeFileStatuses(); + + lastEditedState = hasBeenEdited; + } } diff --git a/extras/Projucer/Source/CodeEditor/jucer_DocumentEditorComponent.h b/extras/Projucer/Source/CodeEditor/jucer_DocumentEditorComponent.h index 3d5af0457a..24a96a7fb2 100644 --- a/extras/Projucer/Source/CodeEditor/jucer_DocumentEditorComponent.h +++ b/extras/Projucer/Source/CodeEditor/jucer_DocumentEditorComponent.h @@ -43,6 +43,7 @@ public: protected: OpenDocumentManager::Document* document; + bool lastEditedState = false; void setEditedState (bool hasBeenEdited); diff --git a/extras/Projucer/Source/Project/UI/Sidebar/jucer_FileTreeItems.h b/extras/Projucer/Source/Project/UI/Sidebar/jucer_FileTreeItems.h index e95d978665..3f5de5055b 100644 --- a/extras/Projucer/Source/Project/UI/Sidebar/jucer_FileTreeItems.h +++ b/extras/Projucer/Source/Project/UI/Sidebar/jucer_FileTreeItems.h @@ -465,6 +465,21 @@ public: return getFile().getFileName(); } + void paintItem (Graphics& g, int width, int height) override + { + JucerTreeViewBase::paintItem (g, width, height); + + if (item.needsSaving()) + { + auto bounds = g.getClipBounds().withY (0).withHeight (height); + + g.setFont (getFont()); + g.setColour (getContentColour (false)); + + g.drawFittedText ("*", bounds.removeFromLeft (height), Justification::centred, 1); + } + } + static File findCorrespondingHeaderOrCpp (const File& f) { if (f.hasFileExtension (sourceFileExtensions)) return f.withFileExtension (".h"); diff --git a/extras/Projucer/Source/Project/UI/jucer_ProjectContentComponent.cpp b/extras/Projucer/Source/Project/UI/jucer_ProjectContentComponent.cpp index 6137807dfa..af10addcd9 100644 --- a/extras/Projucer/Source/Project/UI/jucer_ProjectContentComponent.cpp +++ b/extras/Projucer/Source/Project/UI/jucer_ProjectContentComponent.cpp @@ -334,6 +334,13 @@ void ProjectContentComponent::changeListenerCallback (ChangeBroadcaster*) updateMissingFileStatuses(); } +void ProjectContentComponent::refreshProjectTreeFileStatuses() +{ + if (auto* projectTab = getProjectTab()) + if (auto* fileTree = projectTab->getFileTreePanel()) + fileTree->repaint(); +} + void ProjectContentComponent::updateMissingFileStatuses() { if (auto* pTab = getProjectTab()) @@ -482,6 +489,8 @@ void ProjectContentComponent::saveDocument() { if (! currentDocument->save()) showSaveWarning (currentDocument); + + refreshProjectTreeFileStatuses(); } else { @@ -491,8 +500,13 @@ void ProjectContentComponent::saveDocument() void ProjectContentComponent::saveAs() { - if (currentDocument != nullptr && ! currentDocument->saveAs()) - showSaveWarning (currentDocument); + if (currentDocument != nullptr) + { + if (! currentDocument->saveAs()) + showSaveWarning (currentDocument); + + refreshProjectTreeFileStatuses(); + } } bool ProjectContentComponent::goToPreviousFile() diff --git a/extras/Projucer/Source/Project/UI/jucer_ProjectContentComponent.h b/extras/Projucer/Source/Project/UI/jucer_ProjectContentComponent.h index 758ac33671..6c7254ae68 100644 --- a/extras/Projucer/Source/Project/UI/jucer_ProjectContentComponent.h +++ b/extras/Projucer/Source/Project/UI/jucer_ProjectContentComponent.h @@ -97,6 +97,7 @@ public: void deleteSelectedTreeItems(); + void refreshProjectTreeFileStatuses(); void updateMissingFileStatuses(); void createProjectTabs(); void deleteProjectTabs(); diff --git a/extras/Projucer/Source/Project/jucer_Project.cpp b/extras/Projucer/Source/Project/jucer_Project.cpp index 8131496d3a..599348af1e 100644 --- a/extras/Projucer/Source/Project/jucer_Project.cpp +++ b/extras/Projucer/Source/Project/jucer_Project.cpp @@ -1574,6 +1574,23 @@ bool Project::Item::isIconCrossedOut() const || getFile().hasFileExtension (headerFileExtensions)); } +bool Project::Item::needsSaving() const noexcept +{ + auto& odm = ProjucerApplication::getApp().openDocumentManager; + + if (odm.anyFilesNeedSaving()) + { + for (int i = 0; i < odm.getNumOpenDocuments(); ++i) + { + auto* doc = odm.getOpenDocument (i); + if (doc->needsSaving() && doc->getFile() == getFile()) + return true; + } + } + + return false; +} + //============================================================================== ValueTree Project::getConfigNode() { diff --git a/extras/Projucer/Source/Project/jucer_Project.h b/extras/Projucer/Source/Project/jucer_Project.h index d827414843..ee91e08bca 100644 --- a/extras/Projucer/Source/Project/jucer_Project.h +++ b/extras/Projucer/Source/Project/jucer_Project.h @@ -300,6 +300,8 @@ public: Icon getIcon (bool isOpen = false) const; bool isIconCrossedOut() const; + bool needsSaving() const noexcept; + Project& project; ValueTree state;