diff --git a/extras/Introjucer/Source/Application/jucer_Application.h b/extras/Introjucer/Source/Application/jucer_Application.h index 7f7f9cff48..739ce34a2f 100644 --- a/extras/Introjucer/Source/Application/jucer_Application.h +++ b/extras/Introjucer/Source/Application/jucer_Application.h @@ -303,6 +303,7 @@ public: menu.addCommandItem (commandManager, CommandIDs::goToPreviousDoc); menu.addCommandItem (commandManager, CommandIDs::goToNextDoc); + menu.addCommandItem (commandManager, CommandIDs::goToCounterpart); menu.addSeparator(); const int numDocs = jmin (50, getApp().openDocumentManager.getNumOpenDocuments()); diff --git a/extras/Introjucer/Source/Application/jucer_CommandIDs.h b/extras/Introjucer/Source/Application/jucer_CommandIDs.h index 7988c233a3..07d511eb5d 100644 --- a/extras/Introjucer/Source/Application/jucer_CommandIDs.h +++ b/extras/Introjucer/Source/Application/jucer_CommandIDs.h @@ -49,6 +49,7 @@ namespace CommandIDs static const int closeAllDocuments = 0x201000; static const int goToPreviousDoc = 0x201002; static const int goToNextDoc = 0x201003; + static const int goToCounterpart = 0x201004; static const int toFront = 0x2020a0; static const int toBack = 0x2030a1; diff --git a/extras/Introjucer/Source/Application/jucer_OpenDocumentManager.h b/extras/Introjucer/Source/Application/jucer_OpenDocumentManager.h index e712b7f24f..aba2269099 100644 --- a/extras/Introjucer/Source/Application/jucer_OpenDocumentManager.h +++ b/extras/Introjucer/Source/Application/jucer_OpenDocumentManager.h @@ -62,6 +62,7 @@ public: virtual void fileHasBeenRenamed (const File& newFile) = 0; virtual String getState() const = 0; virtual void restoreState (const String& state) = 0; + virtual File getCounterpartFile() const { return File::nonexistent; } }; //============================================================================== diff --git a/extras/Introjucer/Source/Code Editor/jucer_SourceCodeEditor.h b/extras/Introjucer/Source/Code Editor/jucer_SourceCodeEditor.h index 3e585f6b65..5b02783ca2 100644 --- a/extras/Introjucer/Source/Code Editor/jucer_SourceCodeEditor.h +++ b/extras/Introjucer/Source/Code Editor/jucer_SourceCodeEditor.h @@ -50,6 +50,37 @@ public: String getState() const { return lastState != nullptr ? lastState->toString() : String::empty; } void restoreState (const String& state) { lastState = new CodeEditorComponent::State (state); } + File getCounterpartFile() const + { + const File file (getFile()); + + if (file.hasFileExtension ("cpp;c;mm;m")) + { + const char* extensions[] = { "h", "hpp", nullptr }; + return findCounterpart (file, extensions); + } + else if (file.hasFileExtension ("h;hpp")) + { + const char* extensions[] = { "cpp", "mm", "cc", "cxx", "c", "m", nullptr }; + return findCounterpart (file, extensions); + } + + return File::nonexistent; + } + + static File findCounterpart (const File& file, const char** extensions) + { + while (*extensions != nullptr) + { + const File f (file.withFileExtension (*extensions++)); + + if (f.existsAsFile()) + return f; + } + + return File::nonexistent; + } + void reloadFromFile(); bool save(); diff --git a/extras/Introjucer/Source/Project/jucer_ProjectContentComponent.cpp b/extras/Introjucer/Source/Project/jucer_ProjectContentComponent.cpp index 371f0c21e6..634616a84e 100644 --- a/extras/Introjucer/Source/Project/jucer_ProjectContentComponent.cpp +++ b/extras/Introjucer/Source/Project/jucer_ProjectContentComponent.cpp @@ -434,6 +434,25 @@ bool ProjectContentComponent::goToNextFile() return showDocument (recentDocumentList.getNext(), true); } +bool ProjectContentComponent::canGoToCounterpart() const +{ + return currentDocument != nullptr + && currentDocument->getCounterpartFile().exists(); +} + +bool ProjectContentComponent::goToCounterpart() +{ + if (currentDocument != nullptr) + { + const File file (currentDocument->getCounterpartFile()); + + if (file.exists()) + return showEditorForFile (file, true); + } + + return false; +} + bool ProjectContentComponent::saveProject() { return project != nullptr @@ -502,6 +521,7 @@ void ProjectContentComponent::getAllCommands (Array & commands) CommandIDs::showConfigPanel, CommandIDs::goToPreviousDoc, CommandIDs::goToNextDoc, + CommandIDs::goToCounterpart, StandardApplicationCommandIDs::del }; commands.addArray (ids, numElementsInArray (ids)); @@ -569,6 +589,16 @@ void ProjectContentComponent::getCommandInfo (const CommandID commandID, Applica #endif break; + case CommandIDs::goToCounterpart: + result.setInfo ("Open corresponding header or cpp file", "Open counterpart file", CommandCategories::general, 0); + result.setActive (canGoToCounterpart()); + #if JUCE_MAC + result.defaultKeypresses.add (KeyPress (KeyPress::upKey, ModifierKeys::commandModifier | ModifierKeys::ctrlModifier, 0)); + #else + result.defaultKeypresses.add (KeyPress (KeyPress::upKey, ModifierKeys::ctrlModifier | ModifierKeys::shiftModifier, 0)); + #endif + break; + case CommandIDs::openInIDE: #if JUCE_MAC result.setInfo ("Open in XCode...", @@ -639,6 +669,7 @@ bool ProjectContentComponent::perform (const InvocationInfo& info) case CommandIDs::closeDocument: case CommandIDs::goToPreviousDoc: case CommandIDs::goToNextDoc: + case CommandIDs::goToCounterpart: case CommandIDs::saveAndOpenInIDE: if (reinvokeCommandAfterCancellingModalComps (info)) { @@ -661,6 +692,7 @@ bool ProjectContentComponent::perform (const InvocationInfo& info) case CommandIDs::closeDocument: closeDocument(); break; case CommandIDs::goToPreviousDoc: goToPreviousFile(); break; case CommandIDs::goToNextDoc: goToNextFile(); break; + case CommandIDs::goToCounterpart: goToCounterpart(); break; case CommandIDs::showFilePanel: treeViewTabs.setCurrentTabIndex (0); break; case CommandIDs::showConfigPanel: treeViewTabs.setCurrentTabIndex (1); break; diff --git a/extras/Introjucer/Source/Project/jucer_ProjectContentComponent.h b/extras/Introjucer/Source/Project/jucer_ProjectContentComponent.h index 9364350653..90e8aee2d7 100644 --- a/extras/Introjucer/Source/Project/jucer_ProjectContentComponent.h +++ b/extras/Introjucer/Source/Project/jucer_ProjectContentComponent.h @@ -65,6 +65,8 @@ public: bool goToPreviousFile(); bool goToNextFile(); + bool canGoToCounterpart() const; + bool goToCounterpart(); bool saveProject(); void closeProject(); diff --git a/modules/juce_core/memory/juce_ScopedPointer.h b/modules/juce_core/memory/juce_ScopedPointer.h index 0f47ec5dae..90332ad002 100644 --- a/modules/juce_core/memory/juce_ScopedPointer.h +++ b/modules/juce_core/memory/juce_ScopedPointer.h @@ -168,7 +168,7 @@ public: { // Two ScopedPointers should never be able to refer to the same object - if // this happens, you must have done something dodgy! - jassert (object != other.object); + jassert (object != other.object || this == other.getAddress()); std::swap (object, other.object); }