| @@ -50,6 +50,7 @@ public: | |||
| osSelector.onChange = [this] | |||
| { | |||
| addLabelsAndSetProperties(); | |||
| updateValues(); | |||
| updateFilePathPropertyComponents(); | |||
| }; | |||
| @@ -65,6 +66,7 @@ public: | |||
| addChildComponent (rescanUserPathButton); | |||
| rescanUserPathButton.onClick = [] { ProjucerApplication::getApp().rescanUserPathModules(); }; | |||
| updateValues(); | |||
| updateFilePathPropertyComponents(); | |||
| } | |||
| @@ -154,6 +156,9 @@ private: | |||
| float flashAlpha = 0.0f; | |||
| bool hasFlashed = false; | |||
| ValueWithDefault jucePathValue, juceModulePathValue, userModulePathValue, vst3PathValue, rtasPathValue, aaxPathValue, | |||
| androidSDKPathValue, androidNDKPathValue, clionExePathValue, androidStudioExePathValue; | |||
| //============================================================================== | |||
| void timerCallback() override | |||
| { | |||
| @@ -196,46 +201,38 @@ private: | |||
| { | |||
| pathPropertyComponents.clear(); | |||
| auto& settings = getAppSettings(); | |||
| auto isThisOS = isSelectedOSThisOS(); | |||
| if (isSelectedOSThisOS()) | |||
| { | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (settings.getStoredPath (Ids::jucePath), | |||
| "Path to JUCE", true))); | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (jucePathValue, "Path to JUCE", true, isThisOS))); | |||
| pathPropertyComponents.add (nullptr); | |||
| pathPropertyComponents.add (nullptr); | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (settings.getStoredPath (Ids::defaultJuceModulePath), | |||
| "JUCE Modules", true))); | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (settings.getStoredPath (Ids::defaultUserModulePath), | |||
| "User Modules", true, {}, {}, true))); | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (juceModulePathValue, "JUCE Modules", true, isThisOS))); | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (userModulePathValue, "User Modules", true, isThisOS, {}, {}, true))); | |||
| pathPropertyComponents.add (nullptr); | |||
| pathPropertyComponents.add (nullptr); | |||
| if (getSelectedOS() == TargetOS::linux) | |||
| { | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent ({}, "RTAS SDK", true))); | |||
| pathPropertyComponents.getLast()->setEnabled (false); | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (vst3PathValue, "Custom VST3 SDK", true, isThisOS))); | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent ({}, "AAX SDK", true))); | |||
| pathPropertyComponents.getLast()->setEnabled (false); | |||
| } | |||
| else | |||
| { | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (settings.getStoredPath (Ids::rtasPath), | |||
| "RTAS SDK", true))); | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (settings.getStoredPath (Ids::aaxPath), | |||
| "AAX SDK", true))); | |||
| } | |||
| if (getSelectedOS() == TargetOS::linux) | |||
| { | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (Value(), "AAX SDK", true, isThisOS))); | |||
| pathPropertyComponents.getLast()->setEnabled (false); | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (settings.getStoredPath (Ids::androidSDKPath), | |||
| "Android SDK", true))); | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (settings.getStoredPath (Ids::androidNDKPath), | |||
| "Android NDK", true))); | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (Value(), "RTAS SDK", true, isThisOS))); | |||
| pathPropertyComponents.getLast()->setEnabled (false); | |||
| } | |||
| else | |||
| { | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (aaxPathValue, "AAX SDK", true, isThisOS))); | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (rtasPathValue, "RTAS SDK", true, isThisOS))); | |||
| } | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (settings.getStoredPath (Ids::vst3Path), | |||
| "Custom VST3 SDK", true))); | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (androidSDKPathValue, "Android SDK", true, isThisOS))); | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (androidNDKPathValue, "Android NDK", true, isThisOS))); | |||
| if (isThisOS) | |||
| { | |||
| pathPropertyComponents.add (nullptr); | |||
| #if JUCE_MAC | |||
| @@ -245,54 +242,15 @@ private: | |||
| #else | |||
| String exeLabel ("startup script"); | |||
| #endif | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (settings.getStoredPath (Ids::clionExePath), | |||
| "CLion " + exeLabel, false))); | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (settings.getStoredPath (Ids::androidStudioExePath), | |||
| "Android Studio " + exeLabel, false))); | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (clionExePathValue, "CLion " + exeLabel, false, isThisOS))); | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (androidStudioExePathValue, "Android Studio " + exeLabel, false, isThisOS))); | |||
| rescanJUCEPathButton.setVisible (true); | |||
| rescanUserPathButton.setVisible (true); | |||
| } | |||
| else | |||
| { | |||
| auto selectedOS = getSelectedOS(); | |||
| auto maxChars = 1024; | |||
| pathPropertyComponents.add (nullptr); | |||
| addAndMakeVisible (pathPropertyComponents.add (new TextPropertyComponent (settings.getFallbackPathForOS (Ids::defaultJuceModulePath, selectedOS), | |||
| "JUCE Modules", maxChars, false))); | |||
| addAndMakeVisible (pathPropertyComponents.add (new TextPropertyComponent (settings.getFallbackPathForOS (Ids::defaultUserModulePath, selectedOS), | |||
| "User Modules", maxChars, false))); | |||
| pathPropertyComponents.add (nullptr); | |||
| if (selectedOS == TargetOS::linux) | |||
| { | |||
| addAndMakeVisible (pathPropertyComponents.add (new TextPropertyComponent (Value(), "RTAS SDK", maxChars, false))); | |||
| pathPropertyComponents.getLast()->setEnabled (false); | |||
| addAndMakeVisible (pathPropertyComponents.add (new TextPropertyComponent (Value(), "AAX SDK", maxChars, false))); | |||
| pathPropertyComponents.getLast()->setEnabled (false); | |||
| } | |||
| else | |||
| { | |||
| addAndMakeVisible (pathPropertyComponents.add (new TextPropertyComponent (settings.getFallbackPathForOS (Ids::rtasPath, selectedOS), | |||
| "RTAS SDK", maxChars, false))); | |||
| addAndMakeVisible (pathPropertyComponents.add (new TextPropertyComponent (settings.getFallbackPathForOS (Ids::aaxPath, selectedOS), | |||
| "AAX SDK", maxChars, false))); | |||
| } | |||
| addAndMakeVisible (pathPropertyComponents.add (new TextPropertyComponent (settings.getFallbackPathForOS (Ids::androidSDKPath, selectedOS), | |||
| "Android SDK", maxChars, false))); | |||
| addAndMakeVisible (pathPropertyComponents.add (new TextPropertyComponent (settings.getFallbackPathForOS (Ids::androidNDKPath, selectedOS), | |||
| "Android NDK", maxChars, false))); | |||
| addAndMakeVisible (pathPropertyComponents.add (new TextPropertyComponent (settings.getFallbackPathForOS (Ids::vst3Path, selectedOS), | |||
| "Custom VST3 SDK", maxChars, false))); | |||
| rescanJUCEPathButton.setVisible (false); | |||
| rescanUserPathButton.setVisible (false); | |||
| } | |||
| @@ -300,6 +258,23 @@ private: | |||
| resized(); | |||
| } | |||
| void updateValues() | |||
| { | |||
| auto& settings = getAppSettings(); | |||
| auto os = getSelectedOS(); | |||
| jucePathValue = settings.getStoredPath (Ids::jucePath, os); | |||
| juceModulePathValue = settings.getStoredPath (Ids::defaultJuceModulePath, os); | |||
| userModulePathValue = settings.getStoredPath (Ids::defaultUserModulePath, os); | |||
| vst3PathValue = settings.getStoredPath (Ids::vst3Path, os); | |||
| rtasPathValue = settings.getStoredPath (Ids::rtasPath, os); | |||
| aaxPathValue = settings.getStoredPath (Ids::aaxPath, os); | |||
| androidSDKPathValue = settings.getStoredPath (Ids::androidSDKPath, os); | |||
| androidNDKPathValue = settings.getStoredPath (Ids::androidNDKPath, os); | |||
| clionExePathValue = settings.getStoredPath (Ids::clionExePath, os); | |||
| androidStudioExePathValue = settings.getStoredPath (Ids::androidStudioExePath, os); | |||
| } | |||
| void addLabelsAndSetProperties() | |||
| { | |||
| pathPropertyLabels.clear(); | |||
| @@ -316,5 +291,6 @@ private: | |||
| } | |||
| } | |||
| //============================================================================== | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GlobalPathsWindowComponent) | |||
| }; | |||
| @@ -751,10 +751,10 @@ void LatestVersionChecker::modalStateFinished (int result, | |||
| void LatestVersionChecker::askUserForLocationToDownload (URL& newVersionToDownload, const String& extraHeaders) | |||
| { | |||
| File targetFolder (getAppSettings().getStoredPath (Ids::jucePath).toString()); | |||
| File targetFolder (getAppSettings().getStoredPath (Ids::jucePath, TargetOS::getThisOS()).get()); | |||
| FileChooser chooser (TRANS("Please select the location into which you'd like to install the new version"), | |||
| targetFolder); | |||
| targetFolder); | |||
| if (chooser.browseForDirectory()) | |||
| { | |||
| @@ -462,7 +462,7 @@ private: | |||
| && (project.isConfigFlagEnabled ("JUCE_PLUGINHOST_VST3") | |||
| || project.isConfigFlagEnabled ("JUCE_PLUGINHOST_VST")); | |||
| auto customVst3Path = getAppSettings().getStoredPath (Ids::vst3Path).toString(); | |||
| auto customVst3Path = getAppSettings().getStoredPath (Ids::vst3Path, TargetOS::getThisOS()).get().toString(); | |||
| if (customVst3Path.isNotEmpty() && (project.getProjectType().isAudioPlugin() || isVSTHost)) | |||
| paths.add (customVst3Path); | |||
| @@ -133,7 +133,8 @@ private: | |||
| //============================================================================== | |||
| class ModuleSettingsPanel : public Component, | |||
| private Value::Listener | |||
| private Value::Listener, | |||
| private Timer | |||
| { | |||
| public: | |||
| ModuleSettingsPanel (Project& p, const String& modID, TreeView* tree) | |||
| @@ -163,21 +164,21 @@ private: | |||
| if (modules.doesModuleHaveHigherCppStandardThanProject (moduleID)) | |||
| props.add (new CppStandardWarningComponent()); | |||
| modulePathValueSources.clear(); | |||
| exporterModulePathValues.clear(); | |||
| for (Project::ExporterIterator exporter (project); exporter.next();) | |||
| { | |||
| if (exporter->isCLion()) | |||
| continue; | |||
| auto key = isJUCEModule (moduleID) ? Ids::defaultJuceModulePath | |||
| : Ids::defaultUserModulePath; | |||
| exporterModulePathValues.add (exporter->getPathForModuleValue (moduleID)); | |||
| Value src (modulePathValueSources.add (new DependencyPathValueSource (exporter->getPathForModuleValue (moduleID), | |||
| key, exporter->getTargetOSForExporter()))); | |||
| auto& value = exporterModulePathValues.getReference (exporterModulePathValues.size() - 1); | |||
| value.onDefaultChange = [this] { startTimer (50); }; | |||
| auto* pathComponent = new DependencyFilePathPropertyComponent (src, "Path for " + exporter->getName().quoted(), | |||
| true, "*", project.getProjectFolder()); | |||
| auto* pathComponent = new FilePathPropertyComponent (value, "Path for " + exporter->getName().quoted(), true, | |||
| exporter->getTargetOSForExporter() == TargetOS::getThisOS(), | |||
| "*", project.getProjectFolder()); | |||
| props.add (pathComponent, | |||
| "A path to the folder that contains the " + moduleID + " module when compiling the " | |||
| @@ -187,10 +188,11 @@ private: | |||
| "is empty then the global path will be used."); | |||
| pathComponent->setEnabled (! modules.shouldUseGlobalPath (moduleID)); | |||
| pathComponent->getValue().addListener (this); | |||
| } | |||
| globalPathValue.removeListener (this); | |||
| globalPathValue.referTo (modules.getShouldUseGlobalPathValue (moduleID)); | |||
| globalPathValue.addListener (this); | |||
| auto menuItemString = (TargetOS::getThisOS() == TargetOS::osx ? "\"Projucer->Global Paths...\"" | |||
| : "\"File->Global Paths...\""); | |||
| @@ -200,7 +202,6 @@ private: | |||
| String ("If this is enabled, then the locally-stored global path (set in the ") + menuItemString + " menu item) " | |||
| "will be used as the path to this module. " | |||
| "This means that if this Projucer project is opened on another machine it will use that machine's global path as the path to this module."); | |||
| globalPathValue.addListener (this); | |||
| props.add (new BooleanPropertyComponent (modules.shouldCopyModuleFilesLocally (moduleID), | |||
| "Create local copy", "Copy the module into the project folder"), | |||
| @@ -239,33 +240,19 @@ private: | |||
| String getModuleID() const noexcept { return moduleID; } | |||
| private: | |||
| void valueChanged (Value&) override { startTimer (50); } | |||
| void timerCallback() override { stopTimer(); refresh(); } | |||
| //============================================================================== | |||
| PropertyGroupComponent group; | |||
| Project& project; | |||
| SafePointer<TreeView> modulesTree; | |||
| String moduleID; | |||
| Value globalPathValue; | |||
| Value defaultJuceModulePathValue, defaultUserModulePathValue; | |||
| OwnedArray <Project::ConfigFlag> configFlags; | |||
| ReferenceCountedArray<Value::ValueSource> modulePathValueSources; | |||
| //============================================================================== | |||
| void valueChanged (Value& v) override | |||
| { | |||
| if (v == globalPathValue) | |||
| { | |||
| auto useGlobalPath = globalPathValue.getValue(); | |||
| for (auto prop : group.properties) | |||
| { | |||
| if (auto* pathPropertyComponent = dynamic_cast<DependencyFilePathPropertyComponent*> (prop)) | |||
| pathPropertyComponent->setEnabled (! useGlobalPath); | |||
| } | |||
| } | |||
| OwnedArray <Project::ConfigFlag> configFlags; | |||
| if (auto* infoComponent = dynamic_cast<ModuleInfoComponent*> (group.properties.getUnchecked (0))) | |||
| infoComponent->refresh(); | |||
| } | |||
| Array<ValueWithDefault> exporterModulePathValues; | |||
| Value globalPathValue; | |||
| //============================================================================== | |||
| class ModuleInfoComponent : public PropertyComponent, | |||
| @@ -276,8 +263,7 @@ private: | |||
| : PropertyComponent ("Module", 150), project (p), moduleID (modID) | |||
| { | |||
| for (Project::ExporterIterator exporter (project); exporter.next();) | |||
| listeningValues.add (new Value (exporter->getPathForModuleValue (moduleID))) | |||
| ->addListener (this); | |||
| listeningValues.add (new Value (exporter->getPathForModuleValue (moduleID).getPropertyAsValue()))->addListener (this); | |||
| refresh(); | |||
| } | |||
| @@ -292,7 +292,7 @@ private: | |||
| auto modID = moduleList.getModuleID (i); | |||
| if (modID != moduleToCopy) | |||
| exporter->getPathForModuleValue (modID) = exporter->getPathForModuleValue (moduleToCopy).getValue(); | |||
| exporter->getPathForModuleValue (modID) = exporter->getPathForModuleValue (moduleToCopy).get(); | |||
| } | |||
| } | |||
| } | |||
| @@ -301,7 +301,7 @@ private: | |||
| modulePathClipboard.clear(); | |||
| for (Project::ExporterIterator exporter (project); exporter.next();) | |||
| modulePathClipboard[exporter->getName()] = exporter->getPathForModuleValue (moduleToCopy).getValue(); | |||
| modulePathClipboard[exporter->getName()] = exporter->getPathForModuleValue (moduleToCopy).get(); | |||
| } | |||
| else if (res == pastePathsID) | |||
| { | |||
| @@ -747,9 +747,9 @@ void EnabledModuleList::setLocalCopyModeForAllModules (bool copyLocally) | |||
| File EnabledModuleList::findDefaultModulesFolder (Project& project) | |||
| { | |||
| File globalPath (getAppSettings().getStoredPath (Ids::defaultJuceModulePath).toString()); | |||
| File globalPath (getAppSettings().getStoredPath (Ids::defaultJuceModulePath, TargetOS::getThisOS()).get().toString()); | |||
| if (globalPath != File()) | |||
| if (globalPath.exists()) | |||
| return globalPath; | |||
| for (auto& exporterPathModule : project.getExporterPathsModuleList().getAllModules()) | |||
| @@ -139,7 +139,7 @@ public: | |||
| gradleToolchain (settings, Ids::gradleToolchain, getUndoManager(), "clang"), | |||
| androidPluginVersion (settings, Ids::androidPluginVersion, getUndoManager(), "3.1.3"), | |||
| buildToolsVersion (settings, Ids::buildToolsVersion, getUndoManager(), "28.0.0"), | |||
| AndroidExecutable (getAppSettings().getStoredPath (Ids::androidStudioExePath).toString()) | |||
| AndroidExecutable (getAppSettings().getStoredPath (Ids::androidStudioExePath, TargetOS::getThisOS()).get().toString()) | |||
| { | |||
| name = getName(); | |||
| @@ -816,8 +816,8 @@ private: | |||
| { | |||
| String props; | |||
| props << "ndk.dir=" << sanitisePath (getAppSettings().getStoredPath (Ids::androidNDKPath).toString()) << newLine | |||
| << "sdk.dir=" << sanitisePath (getAppSettings().getStoredPath (Ids::androidSDKPath).toString()) << newLine; | |||
| props << "ndk.dir=" << sanitisePath (getAppSettings().getStoredPath (Ids::androidNDKPath, TargetOS::getThisOS()).get().toString()) << newLine | |||
| << "sdk.dir=" << sanitisePath (getAppSettings().getStoredPath (Ids::androidSDKPath, TargetOS::getThisOS()).get().toString()) << newLine; | |||
| return props; | |||
| } | |||
| @@ -231,7 +231,7 @@ private: | |||
| static File getCLionExecutableOrApp() | |||
| { | |||
| File clionExeOrApp (getAppSettings() | |||
| .getStoredPath (Ids::clionExePath) | |||
| .getStoredPath (Ids::clionExePath, TargetOS::getThisOS()).get() | |||
| .toString() | |||
| .replace ("${user.home}", File::getSpecialLocation (File::userHomeDirectory).getFullPathName())); | |||
| @@ -136,9 +136,9 @@ public: | |||
| //============================================================================== | |||
| void initialiseDependencyPathValues() override | |||
| { | |||
| vst3Path.referTo (Value (new DependencyPathValueSource (getSetting (Ids::vst3Folder), Ids::vst3Path, TargetOS::windows))); | |||
| aaxPath.referTo (Value (new DependencyPathValueSource (getSetting (Ids::aaxFolder), Ids::aaxPath, TargetOS::windows))); | |||
| rtasPath.referTo (Value (new DependencyPathValueSource (getSetting (Ids::rtasFolder), Ids::rtasPath, TargetOS::windows))); | |||
| vst3PathValueWrapper.init (Ids::vst3Path, TargetOS::windows); | |||
| aaxPathValueWrapper .init (Ids::aaxPath, TargetOS::windows); | |||
| rtasPathValueWrapper.init (Ids::rtasPath, TargetOS::windows); | |||
| } | |||
| //============================================================================== | |||
| @@ -1068,7 +1068,7 @@ public: | |||
| //============================================================================== | |||
| RelativePath getAAXIconFile() const | |||
| { | |||
| RelativePath aaxSDK (owner.getAAXPathValue().toString(), RelativePath::projectFolder); | |||
| RelativePath aaxSDK (owner.getAAXPathString(), RelativePath::projectFolder); | |||
| RelativePath projectIcon ("icon.ico", RelativePath::buildTargetFolder); | |||
| if (getOwner().getTargetFolder().getChildFile ("icon.ico").existsAsFile()) | |||
| @@ -1083,7 +1083,7 @@ public: | |||
| { | |||
| if (type == AAXPlugIn) | |||
| { | |||
| RelativePath aaxSDK (owner.getAAXPathValue().toString(), RelativePath::projectFolder); | |||
| RelativePath aaxSDK (owner.getAAXPathString(), RelativePath::projectFolder); | |||
| RelativePath aaxLibsFolder = aaxSDK.getChildFile ("Libs"); | |||
| RelativePath bundleScript = aaxSDK.getChildFile ("Utilities").getChildFile ("CreatePackage.bat"); | |||
| RelativePath iconFilePath = getAAXIconFile(); | |||
| @@ -1174,13 +1174,13 @@ public: | |||
| { | |||
| case AAXPlugIn: | |||
| { | |||
| auto aaxLibsFolder = RelativePath (owner.getAAXPathValue().toString(), RelativePath::projectFolder).getChildFile ("Libs"); | |||
| auto aaxLibsFolder = RelativePath (owner.getAAXPathString(), RelativePath::projectFolder).getChildFile ("Libs"); | |||
| defines.set ("JucePlugin_AAXLibs_path", createRebasedPath (aaxLibsFolder)); | |||
| } | |||
| break; | |||
| case RTASPlugIn: | |||
| { | |||
| RelativePath rtasFolder (owner.getRTASPathValue().toString(), RelativePath::projectFolder); | |||
| RelativePath rtasFolder (owner.getRTASPathString(), RelativePath::projectFolder); | |||
| defines.set ("JucePlugin_WinBag_path", createRebasedPath (rtasFolder.getChildFile ("WinBag"))); | |||
| } | |||
| break; | |||
| @@ -1202,7 +1202,7 @@ public: | |||
| StringArray searchPaths; | |||
| if (type == RTASPlugIn) | |||
| { | |||
| RelativePath rtasFolder (owner.getRTASPathValue().toString(), RelativePath::projectFolder); | |||
| RelativePath rtasFolder (owner.getRTASPathString(), RelativePath::projectFolder); | |||
| static const char* p[] = { "AlturaPorts/TDMPlugins/PluginLibrary/EffectClasses", | |||
| "AlturaPorts/TDMPlugins/PluginLibrary/ProcessClasses", | |||
| @@ -445,9 +445,9 @@ public: | |||
| //============================================================================== | |||
| void initialiseDependencyPathValues() override | |||
| { | |||
| vst3Path.referTo (Value (new DependencyPathValueSource (getSetting (Ids::vst3Folder), Ids::vst3Path, TargetOS::osx))); | |||
| aaxPath. referTo (Value (new DependencyPathValueSource (getSetting (Ids::aaxFolder), Ids::aaxPath, TargetOS::osx))); | |||
| rtasPath.referTo (Value (new DependencyPathValueSource (getSetting (Ids::rtasFolder), Ids::rtasPath, TargetOS::osx))); | |||
| vst3PathValueWrapper.init (Ids::vst3Path, TargetOS::osx); | |||
| aaxPathValueWrapper .init (Ids::aaxPath, TargetOS::osx); | |||
| rtasPathValueWrapper.init (Ids::rtasPath, TargetOS::osx); | |||
| } | |||
| protected: | |||
| @@ -1667,7 +1667,7 @@ public: | |||
| { | |||
| if (type == AAXPlugIn) | |||
| { | |||
| auto aaxLibsFolder = RelativePath (owner.getAAXPathValue().toString(), RelativePath::projectFolder).getChildFile ("Libs"); | |||
| auto aaxLibsFolder = RelativePath (owner.getAAXPathString(), RelativePath::projectFolder).getChildFile ("Libs"); | |||
| String libraryPath (config.isDebug() ? "Debug" : "Release"); | |||
| libraryPath += "/libAAXLibrary_libcpp.a"; | |||
| @@ -1676,7 +1676,7 @@ public: | |||
| } | |||
| else if (type == RTASPlugIn) | |||
| { | |||
| RelativePath rtasFolder (owner.getRTASPathValue().toString(), RelativePath::projectFolder); | |||
| RelativePath rtasFolder (owner.getRTASPathString(), RelativePath::projectFolder); | |||
| extraLibs.add (rtasFolder.getChildFile ("MacBag/Libs/Debug/libPluginLibrary.a")); | |||
| extraLibs.add (rtasFolder.getChildFile ("MacBag/Libs/Release/libPluginLibrary.a")); | |||
| @@ -1689,7 +1689,7 @@ public: | |||
| if (type == RTASPlugIn) | |||
| { | |||
| RelativePath rtasFolder (owner.getRTASPathValue().toString(), RelativePath::projectFolder); | |||
| RelativePath rtasFolder (owner.getRTASPathString(), RelativePath::projectFolder); | |||
| targetExtraSearchPaths.add ("$(DEVELOPER_DIR)/Headers/FlatCarbon"); | |||
| targetExtraSearchPaths.add ("$(SDKROOT)/Developer/Headers/FlatCarbon"); | |||
| @@ -36,6 +36,8 @@ | |||
| #include "jucer_ProjectExport_CLion.h" | |||
| #include "../Utility/UI/PropertyComponents/jucer_FilePathPropertyComponent.h" | |||
| //============================================================================== | |||
| static void addType (Array<ProjectExporter::ExporterTypeInfo>& list, | |||
| const char* name, const void* iconData, int iconDataSize) | |||
| @@ -296,7 +298,24 @@ void ProjectExporter::createPropertyEditors (PropertyListBuilder& props) | |||
| "The location of the folder in which the " + name + " project will be created. " | |||
| "This path can be absolute, but it's much more sensible to make it relative to the jucer project directory."); | |||
| createDependencyPathProperties (props); | |||
| if (shouldBuildTargetType (ProjectType::Target::VST3PlugIn) && project.shouldBuildVST3()) | |||
| { | |||
| props.add (new FilePathPropertyComponent (vst3PathValueWrapper.wrappedValue, "VST3 SDK Folder", true, getTargetOSForExporter() == TargetOS::getThisOS()), | |||
| "If you're building a VST3 plug-in, you can use this field to override the global VST3 SDK path with a project-specific path. " | |||
| "This can be an absolute path, or a path relative to the Projucer project file."); | |||
| } | |||
| if (shouldBuildTargetType (ProjectType::Target::AAXPlugIn) && project.shouldBuildAAX()) | |||
| { | |||
| props.add (new FilePathPropertyComponent (aaxPathValueWrapper.wrappedValue, "AAX SDK Folder", true, getTargetOSForExporter() == TargetOS::getThisOS()), | |||
| "If you're building an AAX plug-in, this must be the folder containing the AAX SDK. This can be an absolute path, or a path relative to the Projucer project file."); | |||
| } | |||
| if (shouldBuildTargetType (ProjectType::Target::RTASPlugIn) && project.shouldBuildRTAS()) | |||
| { | |||
| props.add (new FilePathPropertyComponent (rtasPathValueWrapper.wrappedValue, "RTAS SDK Folder", true, getTargetOSForExporter() == TargetOS::getThisOS()), | |||
| "If you're building an RTAS plug-in, this must be the folder containing the RTAS SDK. This can be an absolute path, or a path relative to the Projucer project file."); | |||
| } | |||
| props.add (new TextPropertyComponent (extraPPDefsValue, "Extra Preprocessor Definitions", 32768, true), | |||
| "Extra preprocessor definitions. Use the form \"NAME1=value NAME2=value\", using whitespace, commas, " | |||
| @@ -327,31 +346,6 @@ void ProjectExporter::createPropertyEditors (PropertyListBuilder& props) | |||
| "Extra comments: This field is not used for code or project generation, it's just a space where you can express your thoughts."); | |||
| } | |||
| void ProjectExporter::createDependencyPathProperties (PropertyListBuilder& props) | |||
| { | |||
| if (shouldBuildTargetType (ProjectType::Target::VST3PlugIn) && project.shouldBuildVST3()) | |||
| { | |||
| if (dynamic_cast<DependencyPathValueSource*> (&getAAXPathValue().getValueSource()) != nullptr) | |||
| props.add (new DependencyPathPropertyComponent (project.getFile().getParentDirectory(), getVST3PathValue(), "VST3 SDK Folder"), | |||
| "If you're building a VST3 plug-in, you can use this field to override the global VST3 SDK path with a project-specific path. " | |||
| "This can be an absolute path, or a path relative to the Projucer project file."); | |||
| } | |||
| if (shouldBuildTargetType (ProjectType::Target::AAXPlugIn) && project.shouldBuildAAX()) | |||
| { | |||
| if (dynamic_cast<DependencyPathValueSource*> (&getAAXPathValue().getValueSource()) != nullptr) | |||
| props.add (new DependencyPathPropertyComponent (project.getFile().getParentDirectory(), getAAXPathValue(), "AAX SDK Folder"), | |||
| "If you're building an AAX plug-in, this must be the folder containing the AAX SDK. This can be an absolute path, or a path relative to the Projucer project file."); | |||
| } | |||
| if (shouldBuildTargetType (ProjectType::Target::RTASPlugIn) && project.shouldBuildRTAS()) | |||
| { | |||
| if (dynamic_cast<DependencyPathValueSource*> (&getRTASPathValue().getValueSource()) != nullptr) | |||
| props.add (new DependencyPathPropertyComponent (project.getFile().getParentDirectory(), getRTASPathValue(), "RTAS SDK Folder"), | |||
| "If you're building an RTAS plug-in, this must be the folder containing the RTAS SDK. This can be an absolute path, or a path relative to the Projucer project file."); | |||
| } | |||
| } | |||
| void ProjectExporter::createIconProperties (PropertyListBuilder& props) | |||
| { | |||
| OwnedArray<Project::Item> images; | |||
| @@ -411,7 +405,7 @@ RelativePath ProjectExporter::getInternalVST3SDKPath() | |||
| void ProjectExporter::addVST3FolderToPath() | |||
| { | |||
| auto vst3Folder = getVST3PathValue().toString(); | |||
| auto vst3Folder = getVST3PathString(); | |||
| if (vst3Folder.isNotEmpty()) | |||
| addToExtraSearchPaths (RelativePath (vst3Folder, RelativePath::projectFolder), 0); | |||
| @@ -421,7 +415,7 @@ void ProjectExporter::addVST3FolderToPath() | |||
| void ProjectExporter::addAAXFoldersToPath() | |||
| { | |||
| auto aaxFolder = getAAXPathValue().toString(); | |||
| auto aaxFolder = getAAXPathString(); | |||
| if (aaxFolder.isNotEmpty()) | |||
| { | |||
| @@ -530,7 +524,13 @@ void ProjectExporter::addToExtraSearchPaths (const RelativePath& pathFromProject | |||
| addProjectPathToBuildPathList (extraSearchPaths, pathFromProjectFolder, index); | |||
| } | |||
| Value ProjectExporter::getPathForModuleValue (const String& moduleID) | |||
| static var getStoredPathForModule (const String& id, const ProjectExporter& exp) | |||
| { | |||
| return getAppSettings().getStoredPath (isJUCEModule (id) ? Ids::defaultJuceModulePath : Ids::defaultUserModulePath, | |||
| exp.getTargetOSForExporter()).get(); | |||
| } | |||
| ValueWithDefault ProjectExporter::getPathForModuleValue (const String& moduleID) | |||
| { | |||
| auto* um = getUndoManager(); | |||
| @@ -544,7 +544,7 @@ Value ProjectExporter::getPathForModuleValue (const String& moduleID) | |||
| paths.appendChild (m, um); | |||
| } | |||
| return m.getPropertyAsValue (Ids::path, um); | |||
| return { m, Ids::path, um, getStoredPathForModule (moduleID, *this) }; | |||
| } | |||
| String ProjectExporter::getPathForModuleString (const String& moduleID) const | |||
| @@ -553,18 +553,7 @@ String ProjectExporter::getPathForModuleString (const String& moduleID) const | |||
| .getChildWithProperty (Ids::ID, moduleID) [Ids::path].toString(); | |||
| if (exporterPath.isEmpty() || project.getEnabledModules().shouldUseGlobalPath (moduleID)) | |||
| { | |||
| auto id = isJUCEModule (moduleID) ? Ids::defaultJuceModulePath | |||
| : Ids::defaultUserModulePath; | |||
| if (TargetOS::getThisOS() != getTargetOSForExporter()) | |||
| return getAppSettings().getFallbackPathForOS (id, getTargetOSForExporter()).toString(); | |||
| if (id == Ids::defaultJuceModulePath) | |||
| return getAppSettings().getStoredPath (Ids::defaultJuceModulePath).toString(); | |||
| return getAppSettings().getStoredPath (Ids::defaultUserModulePath).toString(); | |||
| } | |||
| return getStoredPathForModule (moduleID, *this); | |||
| return exporterPath; | |||
| } | |||
| @@ -635,7 +624,7 @@ void ProjectExporter::updateOldModulePaths() | |||
| { | |||
| for (int i = project.getEnabledModules().getNumModules(); --i >= 0;) | |||
| { | |||
| auto modID = project.getEnabledModules().getModuleID(i); | |||
| auto modID = project.getEnabledModules().getModuleID (i); | |||
| getPathForModuleValue (modID) = getLegacyModulePath (modID).getParentDirectory().toUnixStyle(); | |||
| } | |||
| @@ -661,7 +650,7 @@ void ProjectExporter::createDefaultModulePaths() | |||
| for (int i = project.getEnabledModules().getNumModules(); --i >= 0;) | |||
| { | |||
| auto modID = project.getEnabledModules().getModuleID (i); | |||
| getPathForModuleValue (modID) = exporter->getPathForModuleValue (modID).getValue(); | |||
| getPathForModuleValue (modID) = exporter->getPathForModuleValue (modID); | |||
| } | |||
| return; | |||
| @@ -675,7 +664,7 @@ void ProjectExporter::createDefaultModulePaths() | |||
| for (int i = project.getEnabledModules().getNumModules(); --i >= 0;) | |||
| { | |||
| auto modID = project.getEnabledModules().getModuleID (i); | |||
| getPathForModuleValue (modID) = exporter->getPathForModuleValue (modID).getValue(); | |||
| getPathForModuleValue (modID) = exporter->getPathForModuleValue (modID); | |||
| } | |||
| return; | |||
| @@ -27,7 +27,6 @@ | |||
| #pragma once | |||
| #include "../Project/jucer_Project.h" | |||
| #include "../Utility/UI/PropertyComponents/jucer_DependencyPathPropertyComponent.h" | |||
| #include "../Utility/UI/PropertyComponents/jucer_PropertyComponentsWithEnablement.h" | |||
| class ProjectSaver; | |||
| @@ -152,15 +151,15 @@ public: | |||
| String getExternalLibrariesString() const { return getSearchPathsFromString (externalLibrariesValue.get().toString()).joinIntoString (";"); } | |||
| bool shouldUseGNUExtensions() const { return gnuExtensionsValue.get();} | |||
| bool shouldUseGNUExtensions() const { return gnuExtensionsValue.get(); } | |||
| Value getVST3PathValue() const { return vst3Path; } | |||
| Value getRTASPathValue() const { return rtasPath; } | |||
| Value getAAXPathValue() const { return aaxPath; } | |||
| String getVST3PathString() const { return vst3PathValueWrapper.wrappedValue.get(); } | |||
| String getAAXPathString() const { return aaxPathValueWrapper.wrappedValue.get(); } | |||
| String getRTASPathString() const { return rtasPathValueWrapper.wrappedValue.get(); } | |||
| // NB: this is the path to the parent "modules" folder that contains the named module, not the | |||
| // module folder itself. | |||
| Value getPathForModuleValue (const String& moduleID); | |||
| ValueWithDefault getPathForModuleValue (const String& moduleID); | |||
| String getPathForModuleString (const String& moduleID) const; | |||
| void removePathForModule (const String& moduleID); | |||
| @@ -370,7 +369,37 @@ protected: | |||
| const String projectName; | |||
| const File projectFolder; | |||
| Value vst3Path, rtasPath, aaxPath; // these must be initialised in the specific exporter c'tors! | |||
| //============================================================================== | |||
| // Wraps a ValueWithDefault object that has a default which depends on a global value. | |||
| // Used for the VST3, RTAS and AAX project-specific path options. | |||
| struct ValueWithDefaultWrapper : public Value::Listener | |||
| { | |||
| void init (const Identifier& identifierToUse, TargetOS::OS targetOS) | |||
| { | |||
| identifier = identifierToUse; | |||
| os = targetOS; | |||
| globalValue = getAppSettings().getStoredPath (identifier, os).getPropertyAsValue(); | |||
| globalValue.addListener (this); | |||
| wrappedValue.referTo (tree, identifier, nullptr, getAppSettings().getStoredPath (identifier, os).get()); | |||
| } | |||
| void valueChanged (Value&) override | |||
| { | |||
| wrappedValue.setDefault (getAppSettings().getStoredPath (identifier, os).get()); | |||
| } | |||
| ValueWithDefault wrappedValue; | |||
| Identifier identifier; | |||
| TargetOS::OS os; | |||
| ValueTree tree { "tree" }; | |||
| Value globalValue; | |||
| }; | |||
| ValueWithDefaultWrapper vst3PathValueWrapper, rtasPathValueWrapper, aaxPathValueWrapper; | |||
| ValueWithDefault targetLocationValue, extraCompilerFlagsValue, extraLinkerFlagsValue, externalLibrariesValue, | |||
| userNotesValue, gnuExtensionsValue, bigIconValue, smallIconValue, extraPPDefsValue; | |||
| @@ -211,34 +211,6 @@ void StoredSettings::updateOldProjectSettingsFiles() | |||
| } | |||
| } | |||
| void StoredSettings::checkJUCEPaths() | |||
| { | |||
| auto moduleFolder = projectDefaults.getProperty (Ids::defaultJuceModulePath).toString(); | |||
| auto juceFolder = projectDefaults.getProperty (Ids::jucePath).toString(); | |||
| auto validModuleFolder = moduleFolder.isNotEmpty() && isGlobalPathValid ({}, Ids::defaultJuceModulePath, moduleFolder); | |||
| auto validJuceFolder = juceFolder.isNotEmpty() && isGlobalPathValid ({}, Ids::jucePath, juceFolder); | |||
| if (validModuleFolder && ! validJuceFolder) | |||
| projectDefaults.getPropertyAsValue (Ids::jucePath, nullptr) = File (moduleFolder).getParentDirectory().getFullPathName(); | |||
| else if (! validModuleFolder && validJuceFolder) | |||
| projectDefaults.getPropertyAsValue (Ids::defaultJuceModulePath, nullptr) = File (juceFolder).getChildFile ("modules").getFullPathName(); | |||
| } | |||
| bool StoredSettings::shouldAskUserToSetJUCEPath() noexcept | |||
| { | |||
| if (! isGlobalPathValid ({}, Ids::jucePath, projectDefaults.getProperty (Ids::jucePath).toString()) | |||
| && getGlobalProperties().getValue ("dontAskAboutJUCEPath", {}).isEmpty()) | |||
| return true; | |||
| return false; | |||
| } | |||
| void StoredSettings::setDontAskAboutJUCEPathAgain() noexcept | |||
| { | |||
| getGlobalProperties().setValue ("dontAskAboutJUCEPath", 1); | |||
| } | |||
| //============================================================================== | |||
| void StoredSettings::loadSwatchColours() | |||
| { | |||
| @@ -289,130 +261,23 @@ void StoredSettings::ColourSelectorWithSwatches::setSwatchColour (int index, con | |||
| } | |||
| //============================================================================== | |||
| Value StoredSettings::getStoredPath (const Identifier& key) | |||
| void StoredSettings::changed (bool isProjectDefaults) | |||
| { | |||
| auto v = projectDefaults.getPropertyAsValue (key, nullptr); | |||
| if (v.toString().isEmpty()) | |||
| v = getFallbackPathForOS (key, TargetOS::getThisOS()).toString(); | |||
| std::unique_ptr<XmlElement> data (isProjectDefaults ? projectDefaults.createXml() | |||
| : fallbackPaths.createXml()); | |||
| return v; | |||
| } | |||
| Value StoredSettings::getFallbackPathForOS (const Identifier& key, DependencyPathOS os) | |||
| { | |||
| auto id = identifierForOS (os); | |||
| auto osFallback = fallbackPaths.getOrCreateChildWithName (id, nullptr); | |||
| auto v = osFallback.getPropertyAsValue (key, nullptr); | |||
| if (v.toString().isEmpty()) | |||
| { | |||
| if (key == Ids::jucePath) | |||
| { | |||
| v = (os == TargetOS::windows ? "C:\\JUCE" | |||
| : "~/JUCE"); | |||
| } | |||
| else if (key == Ids::defaultJuceModulePath) | |||
| { | |||
| v = (os == TargetOS::windows ? "C:\\JUCE\\modules" | |||
| : "~/JUCE/modules"); | |||
| } | |||
| else if (key == Ids::defaultUserModulePath) | |||
| { | |||
| v = (os == TargetOS::windows ? "C:\\modules" | |||
| : "~/modules"); | |||
| } | |||
| else if (key == Ids::vst3Path) | |||
| { | |||
| v = ""; | |||
| } | |||
| else if (key == Ids::rtasPath) | |||
| { | |||
| if (os == TargetOS::windows) v = "C:\\SDKs\\PT_90_SDK"; | |||
| else if (os == TargetOS::osx) v = "~/SDKs/PT_90_SDK"; | |||
| else return {}; // no RTAS on this OS! | |||
| } | |||
| else if (key == Ids::aaxPath) | |||
| { | |||
| if (os == TargetOS::windows) v = "C:\\SDKs\\AAX"; | |||
| else if (os == TargetOS::osx) v = "~/SDKs/AAX"; | |||
| else return {}; // no AAX on this OS! | |||
| } | |||
| else if (key == Ids::androidSDKPath) | |||
| { | |||
| v = "${user.home}/Library/Android/sdk"; | |||
| } | |||
| else if (key == Ids::androidNDKPath) | |||
| { | |||
| v = "${user.home}/Library/Android/sdk/ndk-bundle"; | |||
| } | |||
| else if (key == Ids::clionExePath) | |||
| { | |||
| if (os == TargetOS::windows) | |||
| { | |||
| #if JUCE_WINDOWS | |||
| auto regValue = WindowsRegistry::getValue ("HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes\\Applications\\clion64.exe\\shell\\open\\command\\", {}, {}); | |||
| auto openCmd = StringArray::fromTokens (regValue, true); | |||
| if (! openCmd.isEmpty()) | |||
| return Value (openCmd[0].unquoted()); | |||
| #endif | |||
| v = "C:\\Program Files\\JetBrains\\CLion YYYY.MM.DD\\bin\\clion64.exe"; | |||
| } | |||
| else if (os == TargetOS::osx) | |||
| { | |||
| v = "/Applications/CLion.app"; | |||
| } | |||
| else | |||
| { | |||
| v = "${user.home}/clion/bin/clion.sh"; | |||
| } | |||
| } | |||
| else if (key == Ids::androidStudioExePath) | |||
| { | |||
| if (os == TargetOS::windows) | |||
| { | |||
| #if JUCE_WINDOWS | |||
| auto path = WindowsRegistry::getValue ("HKEY_LOCAL_MACHINE\\SOFTWARE\\Android Studio\\Path", {}, {}); | |||
| if (! path.isEmpty()) | |||
| return Value (path.unquoted() + "\\bin\\studio64.exe"); | |||
| #endif | |||
| v = "C:\\Program Files\\Android\\Android Studio\\bin\\studio64.exe"; | |||
| } | |||
| else if (os == TargetOS::osx) | |||
| { | |||
| v = "/Applications/Android Studio.app"; | |||
| } | |||
| else | |||
| { | |||
| return {}; // no Android Studio on this OS! | |||
| } | |||
| } | |||
| } | |||
| return v; | |||
| } | |||
| Identifier StoredSettings::identifierForOS (DependencyPathOS os) noexcept | |||
| { | |||
| if (os == TargetOS::osx) return Ids::osxFallback; | |||
| else if (os == TargetOS::windows) return Ids::windowsFallback; | |||
| else if (os == TargetOS::linux) return Ids::linuxFallback; | |||
| jassertfalse; | |||
| return {}; | |||
| propertyFiles.getUnchecked (0)->setValue (isProjectDefaults ? "PROJECT_DEFAULT_SETTINGS" : "FALLBACK_PATHS", | |||
| data.get()); | |||
| } | |||
| //============================================================================== | |||
| static bool doesSDKPathContainFile (const File& relativeTo, const String& path, const String& fileToCheckFor) noexcept | |||
| { | |||
| auto actualPath = path.replace ("${user.home}", File::getSpecialLocation (File::userHomeDirectory).getFullPathName()); | |||
| return relativeTo.getChildFile (actualPath + "/" + fileToCheckFor).exists(); | |||
| } | |||
| bool StoredSettings::isGlobalPathValid (const File& relativeTo, const Identifier& key, const String& path) const noexcept | |||
| static bool isGlobalPathValid (const File& relativeTo, const Identifier& key, const String& path) | |||
| { | |||
| String fileToCheckFor; | |||
| @@ -483,3 +348,138 @@ bool StoredSettings::isGlobalPathValid (const File& relativeTo, const Identifier | |||
| return doesSDKPathContainFile (relativeTo, path, fileToCheckFor); | |||
| } | |||
| void StoredSettings::checkJUCEPaths() | |||
| { | |||
| auto moduleFolder = getStoredPath (Ids::defaultJuceModulePath, TargetOS::getThisOS()).get().toString(); | |||
| auto juceFolder = getStoredPath (Ids::jucePath, TargetOS::getThisOS()).get().toString(); | |||
| auto validModuleFolder = isGlobalPathValid ({}, Ids::defaultJuceModulePath, moduleFolder); | |||
| auto validJuceFolder = isGlobalPathValid ({}, Ids::jucePath, juceFolder); | |||
| if (validModuleFolder && ! validJuceFolder) | |||
| projectDefaults.getPropertyAsValue (Ids::jucePath, nullptr) = File (moduleFolder).getParentDirectory().getFullPathName(); | |||
| else if (! validModuleFolder && validJuceFolder) | |||
| projectDefaults.getPropertyAsValue (Ids::defaultJuceModulePath, nullptr) = File (juceFolder).getChildFile ("modules").getFullPathName(); | |||
| } | |||
| bool StoredSettings::shouldAskUserToSetJUCEPath() noexcept | |||
| { | |||
| if (! isGlobalPathValid ({}, Ids::jucePath, getStoredPath (Ids::jucePath, TargetOS::getThisOS()).get().toString()) | |||
| && getGlobalProperties().getValue ("dontAskAboutJUCEPath", {}).isEmpty()) | |||
| return true; | |||
| return false; | |||
| } | |||
| void StoredSettings::setDontAskAboutJUCEPathAgain() noexcept | |||
| { | |||
| getGlobalProperties().setValue ("dontAskAboutJUCEPath", 1); | |||
| } | |||
| static String getFallbackPathForOS (const Identifier& key, DependencyPathOS os) | |||
| { | |||
| if (key == Ids::jucePath) | |||
| { | |||
| return (os == TargetOS::windows ? "C:\\JUCE" : "~/JUCE"); | |||
| } | |||
| else if (key == Ids::defaultJuceModulePath) | |||
| { | |||
| return (os == TargetOS::windows ? "C:\\JUCE\\modules" : "~/JUCE/modules"); | |||
| } | |||
| else if (key == Ids::defaultUserModulePath) | |||
| { | |||
| return (os == TargetOS::windows ? "C:\\modules" : "~/modules"); | |||
| } | |||
| else if (key == Ids::vst3Path) | |||
| { | |||
| return {}; | |||
| } | |||
| else if (key == Ids::rtasPath) | |||
| { | |||
| if (os == TargetOS::windows) return "C:\\SDKs\\PT_90_SDK"; | |||
| else if (os == TargetOS::osx) return "~/SDKs/PT_90_SDK"; | |||
| else return {}; // no RTAS on this OS! | |||
| } | |||
| else if (key == Ids::aaxPath) | |||
| { | |||
| if (os == TargetOS::windows) return "C:\\SDKs\\AAX"; | |||
| else if (os == TargetOS::osx) return "~/SDKs/AAX"; | |||
| else return {}; // no AAX on this OS! | |||
| } | |||
| else if (key == Ids::androidSDKPath) | |||
| { | |||
| return "${user.home}/Library/Android/sdk"; | |||
| } | |||
| else if (key == Ids::androidNDKPath) | |||
| { | |||
| return "${user.home}/Library/Android/sdk/ndk-bundle"; | |||
| } | |||
| else if (key == Ids::clionExePath) | |||
| { | |||
| if (os == TargetOS::windows) | |||
| { | |||
| #if JUCE_WINDOWS | |||
| auto regValue = WindowsRegistry::getValue ("HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes\\Applications\\clion64.exe\\shell\\open\\command\\", {}, {}); | |||
| auto openCmd = StringArray::fromTokens (regValue, true); | |||
| if (! openCmd.isEmpty()) | |||
| return openCmd[0].unquoted(); | |||
| #endif | |||
| return "C:\\Program Files\\JetBrains\\CLion YYYY.MM.DD\\bin\\clion64.exe"; | |||
| } | |||
| else if (os == TargetOS::osx) | |||
| { | |||
| return "/Applications/CLion.app"; | |||
| } | |||
| else | |||
| { | |||
| return "${user.home}/clion/bin/clion.sh"; | |||
| } | |||
| } | |||
| else if (key == Ids::androidStudioExePath) | |||
| { | |||
| if (os == TargetOS::windows) | |||
| { | |||
| #if JUCE_WINDOWS | |||
| auto path = WindowsRegistry::getValue ("HKEY_LOCAL_MACHINE\\SOFTWARE\\Android Studio\\Path", {}, {}); | |||
| if (! path.isEmpty()) | |||
| return path.unquoted() + "\\bin\\studio64.exe"; | |||
| #endif | |||
| return "C:\\Program Files\\Android\\Android Studio\\bin\\studio64.exe"; | |||
| } | |||
| else if (os == TargetOS::osx) | |||
| { | |||
| return "/Applications/Android Studio.app"; | |||
| } | |||
| else | |||
| { | |||
| return {}; // no Android Studio on this OS! | |||
| } | |||
| } | |||
| // unknown key! | |||
| jassertfalse; | |||
| return {}; | |||
| } | |||
| static Identifier identifierForOS (DependencyPathOS os) noexcept | |||
| { | |||
| if (os == TargetOS::osx) return Ids::osxFallback; | |||
| else if (os == TargetOS::windows) return Ids::windowsFallback; | |||
| else if (os == TargetOS::linux) return Ids::linuxFallback; | |||
| jassertfalse; | |||
| return {}; | |||
| } | |||
| ValueWithDefault StoredSettings::getStoredPath (const Identifier& key, DependencyPathOS os) | |||
| { | |||
| auto tree = (os == TargetOS::getThisOS() ? projectDefaults | |||
| : fallbackPaths.getOrCreateChildWithName (identifierForOS (os), nullptr)); | |||
| return { tree, key, nullptr, getFallbackPathForOS (key, os) }; | |||
| } | |||
| @@ -62,52 +62,18 @@ public: | |||
| }; | |||
| //============================================================================== | |||
| AppearanceSettings appearance; | |||
| StringArray monospacedFontNames; | |||
| File lastWizardFolder; | |||
| //============================================================================== | |||
| Value getStoredPath (const Identifier& key); | |||
| Value getFallbackPathForOS (const Identifier& key, DependencyPathOS); | |||
| bool isGlobalPathValid (const File& relativeTo, const Identifier& key, const String& path) const noexcept; | |||
| ValueWithDefault getStoredPath (const Identifier& key, DependencyPathOS os); | |||
| //============================================================================== | |||
| bool shouldAskUserToSetJUCEPath() noexcept; | |||
| void setDontAskAboutJUCEPathAgain() noexcept; | |||
| private: | |||
| OwnedArray<PropertiesFile> propertyFiles; | |||
| ValueTree projectDefaults; | |||
| ValueTree fallbackPaths; | |||
| void changed (bool isProjectDefaults) | |||
| { | |||
| std::unique_ptr<XmlElement> data (isProjectDefaults ? projectDefaults.createXml() | |||
| : fallbackPaths.createXml()); | |||
| propertyFiles.getUnchecked (0)->setValue (isProjectDefaults ? "PROJECT_DEFAULT_SETTINGS" | |||
| : "FALLBACK_PATHS", | |||
| data.get()); | |||
| // also override the fallback settings if we are editing the project defaults | |||
| if (isProjectDefaults) | |||
| { | |||
| auto v = fallbackPaths.getOrCreateChildWithName (identifierForOS (TargetOS::getThisOS()), nullptr); | |||
| auto n = projectDefaults.getNumProperties(); | |||
| for (int i = 0; i < n; ++i) | |||
| { | |||
| auto name = projectDefaults.getPropertyName (i); | |||
| v.setProperty (name, projectDefaults.getProperty(name), nullptr); | |||
| } | |||
| changed (false); | |||
| } | |||
| } | |||
| static Identifier identifierForOS (DependencyPathOS os) noexcept; | |||
| //============================================================================== | |||
| AppearanceSettings appearance; | |||
| StringArray monospacedFontNames; | |||
| File lastWizardFolder; | |||
| private: | |||
| //============================================================================== | |||
| void updateGlobalPreferences(); | |||
| void updateRecentFiles(); | |||
| void updateLastWizardFolder(); | |||
| @@ -120,12 +86,20 @@ private: | |||
| void checkJUCEPaths(); | |||
| //============================================================================== | |||
| void changed (bool); | |||
| void valueTreePropertyChanged (ValueTree& vt, const Identifier&) override { changed (vt == projectDefaults); } | |||
| void valueTreeChildAdded (ValueTree& vt, ValueTree&) override { changed (vt == projectDefaults); } | |||
| void valueTreeChildRemoved (ValueTree& vt, ValueTree&, int) override { changed (vt == projectDefaults); } | |||
| void valueTreeChildOrderChanged (ValueTree& vt, int, int) override { changed (vt == projectDefaults); } | |||
| void valueTreeParentChanged (ValueTree& vt) override { changed (vt == projectDefaults); } | |||
| //============================================================================== | |||
| OwnedArray<PropertiesFile> propertyFiles; | |||
| ValueTree projectDefaults; | |||
| ValueTree fallbackPaths; | |||
| //============================================================================== | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StoredSettings) | |||
| }; | |||
| @@ -255,9 +255,9 @@ ValueTree PIPGenerator::createExporterChild (const String& exporterName) | |||
| if (isMobileExporter (exporterName) || (metadata[Ids::name] == "AUv3SynthPlugin" && exporterName == "XCODE_MAC")) | |||
| { | |||
| auto juceDir = getAppSettings().getStoredPath (Ids::jucePath).toString(); | |||
| auto juceDir = getAppSettings().getStoredPath (Ids::jucePath, TargetOS::getThisOS()).get().toString(); | |||
| if (juceDir.isNotEmpty() && isValidJUCEExamplesDirectory (File (juceDir).getChildFile ("examples"))) | |||
| if (isValidJUCEExamplesDirectory (File (juceDir).getChildFile ("examples"))) | |||
| { | |||
| auto assetsDirectoryPath = File (juceDir).getChildFile ("examples").getChildFile ("Assets").getFullPathName(); | |||
| @@ -358,9 +358,9 @@ Result PIPGenerator::setProjectSettings (ValueTree& jucerTree) | |||
| if (useLocalCopy && isJUCEExample (pipFile)) | |||
| { | |||
| auto juceDir = getAppSettings().getStoredPath (Ids::jucePath).toString(); | |||
| auto juceDir = getAppSettings().getStoredPath (Ids::jucePath, TargetOS::getThisOS()).get().toString(); | |||
| if (juceDir.isNotEmpty() && isValidJUCEExamplesDirectory (File (juceDir).getChildFile ("examples"))) | |||
| if (isValidJUCEExamplesDirectory (File (juceDir).getChildFile ("examples"))) | |||
| { | |||
| defines += ((defines.isEmpty() ? "" : " ") + String ("PIP_JUCE_EXAMPLES_DIRECTORY=") | |||
| + Base64::toBase64 (File (juceDir).getChildFile ("examples").getFullPathName())); | |||
| @@ -38,7 +38,7 @@ public: | |||
| useGlobalPathsToggle ("Use global module path") | |||
| { | |||
| if (initialFileOrDirectory.isEmpty()) | |||
| initialFileOrDirectory = getAppSettings().getStoredPath (Ids::defaultJuceModulePath).toString(); | |||
| initialFileOrDirectory = getAppSettings().getStoredPath (Ids::defaultJuceModulePath, TargetOS::getThisOS()).get().toString(); | |||
| setModulesFolder (initialFileOrDirectory); | |||
| @@ -85,7 +85,7 @@ public: | |||
| for (;;) | |||
| { | |||
| FileChooser fc ("Select your JUCE modules folder...", | |||
| { getAppSettings().getStoredPath (Ids::defaultJuceModulePath).toString() }, | |||
| { getAppSettings().getStoredPath (Ids::defaultJuceModulePath, TargetOS::getThisOS()).get().toString() }, | |||
| "*"); | |||
| if (! fc.browseForDirectory()) | |||
| @@ -286,7 +286,7 @@ public: | |||
| WizardComp() | |||
| : platformTargets(), | |||
| projectName (TRANS("Project name")), | |||
| modulesPathBox (getAppSettings().getStoredPath (Ids::defaultJuceModulePath).toString()) | |||
| modulesPathBox (getAppSettings().getStoredPath (Ids::defaultJuceModulePath, TargetOS::getThisOS()).get().toString()) | |||
| { | |||
| setOpaque (false); | |||
| @@ -405,7 +405,7 @@ public: | |||
| } | |||
| wizard->modulesFolder = modulesPathBox.isUsingGlobalPaths ? File (getAppSettings().getStoredPath (Ids::defaultJuceModulePath).toString()) | |||
| wizard->modulesFolder = modulesPathBox.isUsingGlobalPaths ? File (getAppSettings().getStoredPath (Ids::defaultJuceModulePath, TargetOS::getThisOS()).get().toString()) | |||
| : modulesPathBox.modulesFolder; | |||
| if (! isJUCEModulesFolder (wizard->modulesFolder)) | |||
| @@ -419,7 +419,7 @@ public: | |||
| return; | |||
| if (modulesPathBox.isUsingGlobalPaths) | |||
| getAppSettings().getStoredPath (Ids::defaultJuceModulePath).setValue (wizard->modulesFolder.getFullPathName()); | |||
| getAppSettings().getStoredPath (Ids::defaultJuceModulePath, TargetOS::getThisOS()).setValue (wizard->modulesFolder.getFullPathName(), nullptr); | |||
| } | |||
| auto projectDir = fileBrowser.getSelectedFile (0); | |||