| @@ -71,7 +71,6 @@ OBJECTS_APP := \ | |||
| $(JUCE_OBJDIR)/jucer_CommandLine_f35de107.o \ | |||
| $(JUCE_OBJDIR)/jucer_DocumentEditorComponent_695dff1d.o \ | |||
| $(JUCE_OBJDIR)/jucer_DownloadCompileEngineThread_8a38703f.o \ | |||
| $(JUCE_OBJDIR)/jucer_GlobalPreferences_b0f1bd3d.o \ | |||
| $(JUCE_OBJDIR)/jucer_Main_f8488f5b.o \ | |||
| $(JUCE_OBJDIR)/jucer_MainWindow_1e163aeb.o \ | |||
| $(JUCE_OBJDIR)/jucer_OpenDocumentManager_4c72d210.o \ | |||
| @@ -126,6 +125,8 @@ OBJECTS_APP := \ | |||
| .PHONY: clean all | |||
| all : $(JUCE_OUTDIR)/$(JUCE_TARGET_APP) | |||
| $(JUCE_OUTDIR)/$(JUCE_TARGET_APP) : check-pkg-config $(OBJECTS_APP) $(RESOURCES) | |||
| @echo Linking "Projucer - App" | |||
| -$(V_AT)mkdir -p $(JUCE_BINDIR) | |||
| @@ -158,11 +159,6 @@ $(JUCE_OBJDIR)/jucer_DownloadCompileEngineThread_8a38703f.o: ../../Source/Applic | |||
| @echo "Compiling jucer_DownloadCompileEngineThread.cpp" | |||
| $(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<" | |||
| $(JUCE_OBJDIR)/jucer_GlobalPreferences_b0f1bd3d.o: ../../Source/Application/jucer_GlobalPreferences.cpp | |||
| -$(V_AT)mkdir -p $(JUCE_OBJDIR) | |||
| @echo "Compiling jucer_GlobalPreferences.cpp" | |||
| $(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<" | |||
| $(JUCE_OBJDIR)/jucer_Main_f8488f5b.o: ../../Source/Application/jucer_Main.cpp | |||
| -$(V_AT)mkdir -p $(JUCE_OBJDIR) | |||
| @echo "Compiling jucer_Main.cpp" | |||
| @@ -29,7 +29,6 @@ | |||
| 954A036F5DDB375DB23FFB3E = {isa = PBXBuildFile; fileRef = 0400CB0E056A1D840304D2DE; }; | |||
| 3EB3D569250C4BA4CA9AF578 = {isa = PBXBuildFile; fileRef = C7608A3967D9AB9481848F2B; }; | |||
| 636D21BF846031A6A1A7476A = {isa = PBXBuildFile; fileRef = 11EB44786085029106099D01; }; | |||
| 3C3B0ED6C43FDA3AF76DEE2E = {isa = PBXBuildFile; fileRef = 84DE44680C9D37CDDCD127FF; }; | |||
| 95B44E6C74B1DED31DBE37EB = {isa = PBXBuildFile; fileRef = 8C52A3DDA62A746AA7A68535; }; | |||
| AA9D0B8E23F3D87A23DE9F8A = {isa = PBXBuildFile; fileRef = 9069981E414A631B036CC9AC; }; | |||
| 244BA1BDA5FAA465EA3F9C6D = {isa = PBXBuildFile; fileRef = 2247EE920DF0610CAF9F4513; }; | |||
| @@ -115,7 +114,6 @@ | |||
| 1B9B5A37F079FE3B3CF8FAB6 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_graphics.mm"; path = "../../JuceLibraryCode/include_juce_graphics.mm"; sourceTree = "SOURCE_ROOT"; }; | |||
| 1C216FE9B7A5209C5CCF2517 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "jucer_PaintElement.cpp"; path = "../../Source/ComponentEditor/paintelements/jucer_PaintElement.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| 1C73D7591E63E8018E279716 = {isa = PBXFileReference; lastKnownFileType = file.svg; name = "export_android.svg"; path = "../../Source/BinaryData/export_android.svg"; sourceTree = "SOURCE_ROOT"; }; | |||
| 1C81C5501BE7F2C912250711 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_GlobalPreferences.h"; path = "../../Source/Application/jucer_GlobalPreferences.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| 1D3D6A19A60F0B03DE2F1C14 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_PaintElementPath.h"; path = "../../Source/ComponentEditor/paintelements/jucer_PaintElementPath.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| 1D99EA99F946D665FE583414 = {isa = PBXFileReference; lastKnownFileType = file.svg; name = "wizard_Highlight.svg"; path = "../../Source/BinaryData/wizard_Highlight.svg"; sourceTree = "SOURCE_ROOT"; }; | |||
| 1DE5BBC777FB64798D823002 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_data_structures.mm"; path = "../../JuceLibraryCode/include_juce_data_structures.mm"; sourceTree = "SOURCE_ROOT"; }; | |||
| @@ -165,6 +163,7 @@ | |||
| 472F9A90F685220D730EBF6C = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = BinaryData.cpp; path = ../../JuceLibraryCode/BinaryData.cpp; sourceTree = "SOURCE_ROOT"; }; | |||
| 47B49049B85EED74D29C9906 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_ProjectTree_File.h"; path = "../../Source/Project/jucer_ProjectTree_File.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| 47DD50A5A9091F9900E0EAD9 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "jucer_JucerTreeViewBase.cpp"; path = "../../Source/Utility/jucer_JucerTreeViewBase.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| 4856DA6706D794E2D89DAB63 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_GlobalSearchPathsWindowComponent.h"; path = "../../Source/Utility/jucer_GlobalSearchPathsWindowComponent.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| 4A035FB6A8D93BF154C08C3F = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "projucer_BuildTabStatusComp.h"; path = "../../Source/LiveBuildEngine/projucer_BuildTabStatusComp.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| 4A41FD3066D0979DB48691E5 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_MiscUtilities.h"; path = "../../Source/Utility/jucer_MiscUtilities.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| 4A4EBDAD8D098F72CE053235 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_ProjectWizard_AudioPlugin.h"; path = "../../Source/Wizards/jucer_ProjectWizard_AudioPlugin.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| @@ -233,7 +232,6 @@ | |||
| 8138A55052E9FC27284B74DD = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_FontPropertyComponent.h"; path = "../../Source/ComponentEditor/properties/jucer_FontPropertyComponent.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| 820291543BF93243B718F0EE = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_JucerTreeViewBase.h"; path = "../../Source/Utility/jucer_JucerTreeViewBase.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| 842427CFE565F3FCE5B99174 = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DiscRecording.framework; path = System/Library/Frameworks/DiscRecording.framework; sourceTree = SDKROOT; }; | |||
| 84DE44680C9D37CDDCD127FF = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "jucer_GlobalPreferences.cpp"; path = "../../Source/Application/jucer_GlobalPreferences.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| 86E468DE6556BB2AD76A3D80 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "jucer_ProjectContentComponent.cpp"; path = "../../Source/Project/jucer_ProjectContentComponent.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| 86E8A40E5A83781A8478454D = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "jucer_MainTemplate_Window.cpp"; path = "../../Source/BinaryData/jucer_MainTemplate_Window.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| 8702F43110E4CCA5E5F827F5 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AppConfig.h; path = ../../JuceLibraryCode/AppConfig.h; sourceTree = "SOURCE_ROOT"; }; | |||
| @@ -314,6 +312,7 @@ | |||
| C00793A0D4A59BDADC62EEF7 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "projucer_CompileEngineClient.h"; path = "../../Source/LiveBuildEngine/projucer_CompileEngineClient.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| C094F3B6A65A79A6DF87C9C2 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_PaintElementGroup.h"; path = "../../Source/ComponentEditor/paintelements/jucer_PaintElementGroup.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| C09BBB58CA45B66D693E8C31 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_TemplateThumbnailsComponent.h"; path = "../../Source/Wizards/jucer_TemplateThumbnailsComponent.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| C15220EDA1A8315DA3255E87 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_EditorColourSchemeWindowComponent.h"; path = "../../Source/Utility/jucer_EditorColourSchemeWindowComponent.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| C187718F7B9EBA88584B43F3 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "jucer_PaintRoutine.cpp"; path = "../../Source/ComponentEditor/jucer_PaintRoutine.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| C22791DB75870C4F102AA8A3 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_SlidingPanelComponent.h"; path = "../../Source/Utility/jucer_SlidingPanelComponent.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| C2990A8D054BC230E7C637C3 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_NewProjectWizardClasses.h"; path = "../../Source/Wizards/jucer_NewProjectWizardClasses.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| @@ -396,8 +395,6 @@ | |||
| 11EB44786085029106099D01, | |||
| B7307A82D9EB1EDBA91EE43D, | |||
| D526C38D581425949BA0E4AC, | |||
| 84DE44680C9D37CDDCD127FF, | |||
| 1C81C5501BE7F2C912250711, | |||
| F03E2BDD36E6F4F53AB767A8, | |||
| 8C52A3DDA62A746AA7A68535, | |||
| 9069981E414A631B036CC9AC, | |||
| @@ -569,10 +566,12 @@ | |||
| 914ADDB50ED7365F08BA91F9, | |||
| DF78EF6242D82F912534A277, | |||
| 188D03A4247F4BC0539F5C49, | |||
| C15220EDA1A8315DA3255E87, | |||
| 1729AEDC34001C31B8CC357C, | |||
| 553725A0E3A391651ED1731E, | |||
| 35A36102EAD2D2620EE99E7E, | |||
| E382C78A1D837DD98916E86A, | |||
| 4856DA6706D794E2D89DAB63, | |||
| CF21D9DB3AEC0A4DCAB36A99, | |||
| 515FF6E74826E3E3F7273621, | |||
| 47DD50A5A9091F9900E0EAD9, | |||
| @@ -839,7 +838,6 @@ | |||
| 954A036F5DDB375DB23FFB3E, | |||
| 3EB3D569250C4BA4CA9AF578, | |||
| 636D21BF846031A6A1A7476A, | |||
| 3C3B0ED6C43FDA3AF76DEE2E, | |||
| 95B44E6C74B1DED31DBE37EB, | |||
| AA9D0B8E23F3D87A23DE9F8A, | |||
| 244BA1BDA5FAA465EA3F9C6D, | |||
| @@ -16,6 +16,7 @@ | |||
| <PropertyGroup Label="Globals"> | |||
| <ProjectGuid>{E4CFCE31-1AF5-C360-751D-9682E333BE4D}</ProjectGuid> | |||
| <PlatformToolset>v120</PlatformToolset> | |||
| <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion> | |||
| </PropertyGroup> | |||
| <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props"/> | |||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" | |||
| @@ -24,6 +25,7 @@ | |||
| <UseOfMfc>false</UseOfMfc> | |||
| <PlatformToolset>v120</PlatformToolset> | |||
| <PlatformToolset>v120</PlatformToolset> | |||
| <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion> | |||
| </PropertyGroup> | |||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" | |||
| Label="Configuration"> | |||
| @@ -32,6 +34,7 @@ | |||
| <WholeProgramOptimization>true</WholeProgramOptimization> | |||
| <PlatformToolset>v120</PlatformToolset> | |||
| <PlatformToolset>v120</PlatformToolset> | |||
| <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion> | |||
| </PropertyGroup> | |||
| <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props"/> | |||
| <ImportGroup Label="ExtensionSettings"/> | |||
| @@ -42,6 +45,7 @@ | |||
| </ImportGroup> | |||
| <PropertyGroup Label="UserMacros"> | |||
| <PlatformToolset>v120</PlatformToolset> | |||
| <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion> | |||
| </PropertyGroup> | |||
| <PropertyGroup> | |||
| <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion> | |||
| @@ -55,6 +59,7 @@ | |||
| <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Projucer</TargetName> | |||
| <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</GenerateManifest> | |||
| <PlatformToolset>v120</PlatformToolset> | |||
| <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion> | |||
| </PropertyGroup> | |||
| <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | |||
| <Midl> | |||
| @@ -146,7 +151,6 @@ | |||
| <ClCompile Include="..\..\Source\Application\jucer_CommandLine.cpp"/> | |||
| <ClCompile Include="..\..\Source\Application\jucer_DocumentEditorComponent.cpp"/> | |||
| <ClCompile Include="..\..\Source\Application\jucer_DownloadCompileEngineThread.cpp"/> | |||
| <ClCompile Include="..\..\Source\Application\jucer_GlobalPreferences.cpp"/> | |||
| <ClCompile Include="..\..\Source\Application\jucer_Main.cpp"/> | |||
| <ClCompile Include="..\..\Source\Application\jucer_MainWindow.cpp"/> | |||
| <ClCompile Include="..\..\Source\Application\jucer_OpenDocumentManager.cpp"/> | |||
| @@ -1376,7 +1380,6 @@ | |||
| <ClInclude Include="..\..\Source\Application\jucer_DocumentEditorComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Application\jucer_DownloadCompileEngineThread.h"/> | |||
| <ClInclude Include="..\..\Source\Application\jucer_FilePreviewComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Application\jucer_GlobalPreferences.h"/> | |||
| <ClInclude Include="..\..\Source\jucer_Headers.h"/> | |||
| <ClInclude Include="..\..\Source\Application\jucer_MainWindow.h"/> | |||
| <ClInclude Include="..\..\Source\Application\jucer_OpenDocumentManager.h"/> | |||
| @@ -1496,9 +1499,11 @@ | |||
| <ClInclude Include="..\..\Source\Utility\jucer_CodeHelpers.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_ColourPropertyComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_Colours.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_EditorColourSchemeWindowComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_FileHelpers.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_FilePathPropertyComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_FloatingToolWindow.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_GlobalSearchPathsWindowComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_Icons.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_JucerTreeViewBase.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_MiscUtilities.h"/> | |||
| @@ -286,9 +286,6 @@ | |||
| <ClCompile Include="..\..\Source\Application\jucer_DownloadCompileEngineThread.cpp"> | |||
| <Filter>Projucer\Application</Filter> | |||
| </ClCompile> | |||
| <ClCompile Include="..\..\Source\Application\jucer_GlobalPreferences.cpp"> | |||
| <Filter>Projucer\Application</Filter> | |||
| </ClCompile> | |||
| <ClCompile Include="..\..\Source\Application\jucer_Main.cpp"> | |||
| <Filter>Projucer\Application</Filter> | |||
| </ClCompile> | |||
| @@ -1719,9 +1716,6 @@ | |||
| <ClInclude Include="..\..\Source\Application\jucer_FilePreviewComponent.h"> | |||
| <Filter>Projucer\Application</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\Source\Application\jucer_GlobalPreferences.h"> | |||
| <Filter>Projucer\Application</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\Source\jucer_Headers.h"> | |||
| <Filter>Projucer\Application</Filter> | |||
| </ClInclude> | |||
| @@ -2079,6 +2073,9 @@ | |||
| <ClInclude Include="..\..\Source\Utility\jucer_Colours.h"> | |||
| <Filter>Projucer\Utility</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_EditorColourSchemeWindowComponent.h"> | |||
| <Filter>Projucer\Utility</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_FileHelpers.h"> | |||
| <Filter>Projucer\Utility</Filter> | |||
| </ClInclude> | |||
| @@ -2088,6 +2085,9 @@ | |||
| <ClInclude Include="..\..\Source\Utility\jucer_FloatingToolWindow.h"> | |||
| <Filter>Projucer\Utility</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_GlobalSearchPathsWindowComponent.h"> | |||
| <Filter>Projucer\Utility</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_Icons.h"> | |||
| <Filter>Projucer\Utility</Filter> | |||
| </ClInclude> | |||
| @@ -16,6 +16,7 @@ | |||
| <PropertyGroup Label="Globals"> | |||
| <ProjectGuid>{E4CFCE31-1AF5-C360-751D-9682E333BE4D}</ProjectGuid> | |||
| <PlatformToolset>v140</PlatformToolset> | |||
| <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion> | |||
| </PropertyGroup> | |||
| <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props"/> | |||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" | |||
| @@ -24,6 +25,7 @@ | |||
| <UseOfMfc>false</UseOfMfc> | |||
| <PlatformToolset>v140</PlatformToolset> | |||
| <PlatformToolset>v140</PlatformToolset> | |||
| <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion> | |||
| </PropertyGroup> | |||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" | |||
| Label="Configuration"> | |||
| @@ -32,6 +34,7 @@ | |||
| <WholeProgramOptimization>true</WholeProgramOptimization> | |||
| <PlatformToolset>v140</PlatformToolset> | |||
| <PlatformToolset>v140</PlatformToolset> | |||
| <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion> | |||
| </PropertyGroup> | |||
| <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props"/> | |||
| <ImportGroup Label="ExtensionSettings"/> | |||
| @@ -42,6 +45,7 @@ | |||
| </ImportGroup> | |||
| <PropertyGroup Label="UserMacros"> | |||
| <PlatformToolset>v140</PlatformToolset> | |||
| <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion> | |||
| </PropertyGroup> | |||
| <PropertyGroup> | |||
| <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion> | |||
| @@ -55,6 +59,7 @@ | |||
| <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Projucer</TargetName> | |||
| <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</GenerateManifest> | |||
| <PlatformToolset>v140</PlatformToolset> | |||
| <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion> | |||
| </PropertyGroup> | |||
| <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | |||
| <Midl> | |||
| @@ -146,7 +151,6 @@ | |||
| <ClCompile Include="..\..\Source\Application\jucer_CommandLine.cpp"/> | |||
| <ClCompile Include="..\..\Source\Application\jucer_DocumentEditorComponent.cpp"/> | |||
| <ClCompile Include="..\..\Source\Application\jucer_DownloadCompileEngineThread.cpp"/> | |||
| <ClCompile Include="..\..\Source\Application\jucer_GlobalPreferences.cpp"/> | |||
| <ClCompile Include="..\..\Source\Application\jucer_Main.cpp"/> | |||
| <ClCompile Include="..\..\Source\Application\jucer_MainWindow.cpp"/> | |||
| <ClCompile Include="..\..\Source\Application\jucer_OpenDocumentManager.cpp"/> | |||
| @@ -1376,7 +1380,6 @@ | |||
| <ClInclude Include="..\..\Source\Application\jucer_DocumentEditorComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Application\jucer_DownloadCompileEngineThread.h"/> | |||
| <ClInclude Include="..\..\Source\Application\jucer_FilePreviewComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Application\jucer_GlobalPreferences.h"/> | |||
| <ClInclude Include="..\..\Source\jucer_Headers.h"/> | |||
| <ClInclude Include="..\..\Source\Application\jucer_MainWindow.h"/> | |||
| <ClInclude Include="..\..\Source\Application\jucer_OpenDocumentManager.h"/> | |||
| @@ -1496,9 +1499,11 @@ | |||
| <ClInclude Include="..\..\Source\Utility\jucer_CodeHelpers.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_ColourPropertyComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_Colours.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_EditorColourSchemeWindowComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_FileHelpers.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_FilePathPropertyComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_FloatingToolWindow.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_GlobalSearchPathsWindowComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_Icons.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_JucerTreeViewBase.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_MiscUtilities.h"/> | |||
| @@ -286,9 +286,6 @@ | |||
| <ClCompile Include="..\..\Source\Application\jucer_DownloadCompileEngineThread.cpp"> | |||
| <Filter>Projucer\Application</Filter> | |||
| </ClCompile> | |||
| <ClCompile Include="..\..\Source\Application\jucer_GlobalPreferences.cpp"> | |||
| <Filter>Projucer\Application</Filter> | |||
| </ClCompile> | |||
| <ClCompile Include="..\..\Source\Application\jucer_Main.cpp"> | |||
| <Filter>Projucer\Application</Filter> | |||
| </ClCompile> | |||
| @@ -1719,9 +1716,6 @@ | |||
| <ClInclude Include="..\..\Source\Application\jucer_FilePreviewComponent.h"> | |||
| <Filter>Projucer\Application</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\Source\Application\jucer_GlobalPreferences.h"> | |||
| <Filter>Projucer\Application</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\Source\jucer_Headers.h"> | |||
| <Filter>Projucer\Application</Filter> | |||
| </ClInclude> | |||
| @@ -2079,6 +2073,9 @@ | |||
| <ClInclude Include="..\..\Source\Utility\jucer_Colours.h"> | |||
| <Filter>Projucer\Utility</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_EditorColourSchemeWindowComponent.h"> | |||
| <Filter>Projucer\Utility</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_FileHelpers.h"> | |||
| <Filter>Projucer\Utility</Filter> | |||
| </ClInclude> | |||
| @@ -2088,6 +2085,9 @@ | |||
| <ClInclude Include="..\..\Source\Utility\jucer_FloatingToolWindow.h"> | |||
| <Filter>Projucer\Utility</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_GlobalSearchPathsWindowComponent.h"> | |||
| <Filter>Projucer\Utility</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_Icons.h"> | |||
| <Filter>Projucer\Utility</Filter> | |||
| </ClInclude> | |||
| @@ -16,6 +16,7 @@ | |||
| <PropertyGroup Label="Globals"> | |||
| <ProjectGuid>{E4CFCE31-1AF5-C360-751D-9682E333BE4D}</ProjectGuid> | |||
| <PlatformToolset>v141</PlatformToolset> | |||
| <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion> | |||
| </PropertyGroup> | |||
| <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props"/> | |||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" | |||
| @@ -24,6 +25,7 @@ | |||
| <UseOfMfc>false</UseOfMfc> | |||
| <PlatformToolset>v141</PlatformToolset> | |||
| <PlatformToolset>v141</PlatformToolset> | |||
| <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion> | |||
| </PropertyGroup> | |||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" | |||
| Label="Configuration"> | |||
| @@ -32,6 +34,7 @@ | |||
| <WholeProgramOptimization>true</WholeProgramOptimization> | |||
| <PlatformToolset>v141</PlatformToolset> | |||
| <PlatformToolset>v141</PlatformToolset> | |||
| <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion> | |||
| </PropertyGroup> | |||
| <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props"/> | |||
| <ImportGroup Label="ExtensionSettings"/> | |||
| @@ -42,6 +45,7 @@ | |||
| </ImportGroup> | |||
| <PropertyGroup Label="UserMacros"> | |||
| <PlatformToolset>v141</PlatformToolset> | |||
| <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion> | |||
| </PropertyGroup> | |||
| <PropertyGroup> | |||
| <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion> | |||
| @@ -55,6 +59,7 @@ | |||
| <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Projucer</TargetName> | |||
| <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</GenerateManifest> | |||
| <PlatformToolset>v141</PlatformToolset> | |||
| <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion> | |||
| </PropertyGroup> | |||
| <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | |||
| <Midl> | |||
| @@ -146,7 +151,6 @@ | |||
| <ClCompile Include="..\..\Source\Application\jucer_CommandLine.cpp"/> | |||
| <ClCompile Include="..\..\Source\Application\jucer_DocumentEditorComponent.cpp"/> | |||
| <ClCompile Include="..\..\Source\Application\jucer_DownloadCompileEngineThread.cpp"/> | |||
| <ClCompile Include="..\..\Source\Application\jucer_GlobalPreferences.cpp"/> | |||
| <ClCompile Include="..\..\Source\Application\jucer_Main.cpp"/> | |||
| <ClCompile Include="..\..\Source\Application\jucer_MainWindow.cpp"/> | |||
| <ClCompile Include="..\..\Source\Application\jucer_OpenDocumentManager.cpp"/> | |||
| @@ -1376,7 +1380,6 @@ | |||
| <ClInclude Include="..\..\Source\Application\jucer_DocumentEditorComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Application\jucer_DownloadCompileEngineThread.h"/> | |||
| <ClInclude Include="..\..\Source\Application\jucer_FilePreviewComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Application\jucer_GlobalPreferences.h"/> | |||
| <ClInclude Include="..\..\Source\jucer_Headers.h"/> | |||
| <ClInclude Include="..\..\Source\Application\jucer_MainWindow.h"/> | |||
| <ClInclude Include="..\..\Source\Application\jucer_OpenDocumentManager.h"/> | |||
| @@ -1496,9 +1499,11 @@ | |||
| <ClInclude Include="..\..\Source\Utility\jucer_CodeHelpers.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_ColourPropertyComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_Colours.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_EditorColourSchemeWindowComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_FileHelpers.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_FilePathPropertyComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_FloatingToolWindow.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_GlobalSearchPathsWindowComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_Icons.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_JucerTreeViewBase.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_MiscUtilities.h"/> | |||
| @@ -286,9 +286,6 @@ | |||
| <ClCompile Include="..\..\Source\Application\jucer_DownloadCompileEngineThread.cpp"> | |||
| <Filter>Projucer\Application</Filter> | |||
| </ClCompile> | |||
| <ClCompile Include="..\..\Source\Application\jucer_GlobalPreferences.cpp"> | |||
| <Filter>Projucer\Application</Filter> | |||
| </ClCompile> | |||
| <ClCompile Include="..\..\Source\Application\jucer_Main.cpp"> | |||
| <Filter>Projucer\Application</Filter> | |||
| </ClCompile> | |||
| @@ -1719,9 +1716,6 @@ | |||
| <ClInclude Include="..\..\Source\Application\jucer_FilePreviewComponent.h"> | |||
| <Filter>Projucer\Application</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\Source\Application\jucer_GlobalPreferences.h"> | |||
| <Filter>Projucer\Application</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\Source\jucer_Headers.h"> | |||
| <Filter>Projucer\Application</Filter> | |||
| </ClInclude> | |||
| @@ -2079,6 +2073,9 @@ | |||
| <ClInclude Include="..\..\Source\Utility\jucer_Colours.h"> | |||
| <Filter>Projucer\Utility</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_EditorColourSchemeWindowComponent.h"> | |||
| <Filter>Projucer\Utility</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_FileHelpers.h"> | |||
| <Filter>Projucer\Utility</Filter> | |||
| </ClInclude> | |||
| @@ -2088,6 +2085,9 @@ | |||
| <ClInclude Include="..\..\Source\Utility\jucer_FloatingToolWindow.h"> | |||
| <Filter>Projucer\Utility</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_GlobalSearchPathsWindowComponent.h"> | |||
| <Filter>Projucer\Utility</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\Source\Utility\jucer_Icons.h"> | |||
| <Filter>Projucer\Utility</Filter> | |||
| </ClInclude> | |||
| @@ -74,7 +74,7 @@ | |||
| // juce_core flags: | |||
| #ifndef JUCE_FORCE_DEBUG | |||
| //#define JUCE_FORCE_DEBUG | |||
| //#define JUCE_FORCE_DEBUG 1 | |||
| #endif | |||
| #ifndef JUCE_LOG_ASSERTIONS | |||
| @@ -82,15 +82,15 @@ | |||
| #endif | |||
| #ifndef JUCE_CHECK_MEMORY_LEAKS | |||
| //#define JUCE_CHECK_MEMORY_LEAKS | |||
| //#define JUCE_CHECK_MEMORY_LEAKS 1 | |||
| #endif | |||
| #ifndef JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES | |||
| //#define JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES | |||
| //#define JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES 1 | |||
| #endif | |||
| #ifndef JUCE_INCLUDE_ZLIB_CODE | |||
| //#define JUCE_INCLUDE_ZLIB_CODE | |||
| //#define JUCE_INCLUDE_ZLIB_CODE 1 | |||
| #endif | |||
| #ifndef JUCE_USE_CURL | |||
| @@ -98,59 +98,59 @@ | |||
| #endif | |||
| #ifndef JUCE_CATCH_UNHANDLED_EXCEPTIONS | |||
| //#define JUCE_CATCH_UNHANDLED_EXCEPTIONS | |||
| //#define JUCE_CATCH_UNHANDLED_EXCEPTIONS 1 | |||
| #endif | |||
| #ifndef JUCE_ALLOW_STATIC_NULL_VARIABLES | |||
| //#define JUCE_ALLOW_STATIC_NULL_VARIABLES | |||
| //#define JUCE_ALLOW_STATIC_NULL_VARIABLES 1 | |||
| #endif | |||
| //============================================================================== | |||
| // juce_events flags: | |||
| #ifndef JUCE_EXECUTE_APP_SUSPEND_ON_IOS_BACKGROUND_TASK | |||
| //#define JUCE_EXECUTE_APP_SUSPEND_ON_IOS_BACKGROUND_TASK | |||
| //#define JUCE_EXECUTE_APP_SUSPEND_ON_IOS_BACKGROUND_TASK 1 | |||
| #endif | |||
| //============================================================================== | |||
| // juce_graphics flags: | |||
| #ifndef JUCE_USE_COREIMAGE_LOADER | |||
| //#define JUCE_USE_COREIMAGE_LOADER | |||
| //#define JUCE_USE_COREIMAGE_LOADER 1 | |||
| #endif | |||
| #ifndef JUCE_USE_DIRECTWRITE | |||
| //#define JUCE_USE_DIRECTWRITE | |||
| //#define JUCE_USE_DIRECTWRITE 1 | |||
| #endif | |||
| //============================================================================== | |||
| // juce_gui_basics flags: | |||
| #ifndef JUCE_ENABLE_REPAINT_DEBUGGING | |||
| //#define JUCE_ENABLE_REPAINT_DEBUGGING | |||
| //#define JUCE_ENABLE_REPAINT_DEBUGGING 1 | |||
| #endif | |||
| #ifndef JUCE_USE_XSHM | |||
| //#define JUCE_USE_XSHM | |||
| //#define JUCE_USE_XSHM 1 | |||
| #endif | |||
| #ifndef JUCE_USE_XRENDER | |||
| //#define JUCE_USE_XRENDER | |||
| //#define JUCE_USE_XRENDER 1 | |||
| #endif | |||
| #ifndef JUCE_USE_XCURSOR | |||
| //#define JUCE_USE_XCURSOR | |||
| //#define JUCE_USE_XCURSOR 1 | |||
| #endif | |||
| //============================================================================== | |||
| // juce_gui_extra flags: | |||
| #ifndef JUCE_WEB_BROWSER | |||
| //#define JUCE_WEB_BROWSER | |||
| //#define JUCE_WEB_BROWSER 1 | |||
| #endif | |||
| #ifndef JUCE_ENABLE_LIVE_CONSTANT_EDITOR | |||
| //#define JUCE_ENABLE_LIVE_CONSTANT_EDITOR | |||
| //#define JUCE_ENABLE_LIVE_CONSTANT_EDITOR 1 | |||
| #endif | |||
| //============================================================================== | |||
| #ifndef JUCE_STANDALONE_APPLICATION | |||
| @@ -136,10 +136,6 @@ | |||
| resource="0" file="Source/Application/jucer_DownloadCompileEngineThread.h"/> | |||
| <FILE id="eo4r70" name="jucer_FilePreviewComponent.h" compile="0" resource="0" | |||
| file="Source/Application/jucer_FilePreviewComponent.h"/> | |||
| <FILE id="Hq3STq" name="jucer_GlobalPreferences.cpp" compile="1" resource="0" | |||
| file="Source/Application/jucer_GlobalPreferences.cpp"/> | |||
| <FILE id="Ym81lY" name="jucer_GlobalPreferences.h" compile="0" resource="0" | |||
| file="Source/Application/jucer_GlobalPreferences.h"/> | |||
| <FILE id="YVE38f" name="jucer_Headers.h" compile="0" resource="0" file="Source/jucer_Headers.h"/> | |||
| <FILE id="eMFQFu" name="jucer_Main.cpp" compile="1" resource="0" file="Source/Application/jucer_Main.cpp"/> | |||
| <FILE id="WuEh1e" name="jucer_MainWindow.cpp" compile="1" resource="0" | |||
| @@ -467,6 +463,8 @@ | |||
| <FILE id="ZZK5JV" name="jucer_ColourPropertyComponent.h" compile="0" | |||
| resource="0" file="Source/Utility/jucer_ColourPropertyComponent.h"/> | |||
| <FILE id="Y5kN1C" name="jucer_Colours.h" compile="0" resource="0" file="Source/Utility/jucer_Colours.h"/> | |||
| <FILE id="DYaDr0" name="jucer_EditorColourSchemeWindowComponent.h" | |||
| compile="0" resource="0" file="Source/Utility/jucer_EditorColourSchemeWindowComponent.h"/> | |||
| <FILE id="Wmahr3" name="jucer_FileHelpers.cpp" compile="1" resource="0" | |||
| file="Source/Utility/jucer_FileHelpers.cpp"/> | |||
| <FILE id="UhuxIZ" name="jucer_FileHelpers.h" compile="0" resource="0" | |||
| @@ -475,6 +473,8 @@ | |||
| resource="0" file="Source/Utility/jucer_FilePathPropertyComponent.h"/> | |||
| <FILE id="bFaUy6" name="jucer_FloatingToolWindow.h" compile="0" resource="0" | |||
| file="Source/Utility/jucer_FloatingToolWindow.h"/> | |||
| <FILE id="AZcyKs" name="jucer_GlobalSearchPathsWindowComponent.h" compile="0" | |||
| resource="0" file="Source/Utility/jucer_GlobalSearchPathsWindowComponent.h"/> | |||
| <FILE id="alvpK9" name="jucer_Icons.cpp" compile="1" resource="0" file="Source/Utility/jucer_Icons.cpp"/> | |||
| <FILE id="iTXdnI" name="jucer_Icons.h" compile="0" resource="0" file="Source/Utility/jucer_Icons.h"/> | |||
| <FILE id="umjCJo" name="jucer_JucerTreeViewBase.cpp" compile="1" resource="0" | |||
| @@ -27,7 +27,6 @@ | |||
| #include "../jucer_Headers.h" | |||
| #include "jucer_Application.h" | |||
| #include "jucer_AppearanceSettings.h" | |||
| #include "jucer_GlobalPreferences.h" | |||
| //============================================================================== | |||
| AppearanceSettings::AppearanceSettings (bool updateAppWhenChanged) | |||
| @@ -55,9 +55,6 @@ public: | |||
| static Font getDefaultCodeFont(); | |||
| static void showGlobalPreferences (ScopedPointer<Component>& ownerPointer, | |||
| bool showCodeEditorTab = false); | |||
| static const char* getSchemeFileSuffix() { return ".scheme"; } | |||
| static const char* getSchemeFileWildCard() { return "*.scheme"; } | |||
| @@ -196,11 +196,11 @@ void ProjucerApplication::shutdown() | |||
| } | |||
| versionChecker = nullptr; | |||
| appearanceEditorWindow = nullptr; | |||
| globalPreferencesWindow = nullptr; | |||
| utf8Window = nullptr; | |||
| svgPathWindow = nullptr; | |||
| aboutWindow = nullptr; | |||
| pathsWindow = nullptr; | |||
| editorColourSchemeWindow = nullptr; | |||
| if (licenseController != nullptr) | |||
| { | |||
| @@ -386,7 +386,7 @@ void ProjucerApplication::createFileMenu (PopupMenu& menu) | |||
| #if ! JUCE_MAC | |||
| menu.addCommandItem (commandManager, CommandIDs::showAboutWindow); | |||
| menu.addCommandItem (commandManager, CommandIDs::showAppUsageWindow); | |||
| menu.addCommandItem (commandManager, CommandIDs::showGlobalPreferences); | |||
| menu.addCommandItem (commandManager, CommandIDs::showGlobalPathsWindow); | |||
| menu.addSeparator(); | |||
| menu.addCommandItem (commandManager, StandardApplicationCommandIDs::quit); | |||
| #endif | |||
| @@ -463,7 +463,7 @@ void ProjucerApplication::createColourSchemeItems (PopupMenu& menu) | |||
| for (auto s : schemes) | |||
| { | |||
| editorColourSchemes.addItem (codeEditorColourSchemeBaseID + i, s, | |||
| globalPreferencesWindow == nullptr, | |||
| editorColourSchemeWindow == nullptr, | |||
| selectedEditorColourSchemeIndex == i); | |||
| ++i; | |||
| } | |||
| @@ -472,7 +472,7 @@ void ProjucerApplication::createColourSchemeItems (PopupMenu& menu) | |||
| editorColourSchemes.addSeparator(); | |||
| editorColourSchemes.addItem (codeEditorColourSchemeBaseID + numEditorColourSchemes, | |||
| "Create...", globalPreferencesWindow == nullptr); | |||
| "Create...", editorColourSchemeWindow == nullptr); | |||
| menu.addSubMenu ("Editor Colour Scheme", editorColourSchemes); | |||
| } | |||
| @@ -511,7 +511,7 @@ void ProjucerApplication::createExtraAppleMenuItems (PopupMenu& menu) | |||
| menu.addCommandItem (commandManager, CommandIDs::showAboutWindow); | |||
| menu.addCommandItem (commandManager, CommandIDs::showAppUsageWindow); | |||
| menu.addSeparator(); | |||
| menu.addCommandItem (commandManager, CommandIDs::showGlobalPreferences); | |||
| menu.addCommandItem (commandManager, CommandIDs::showGlobalPathsWindow); | |||
| } | |||
| void ProjucerApplication::handleMainMenuCommand (int menuItemID) | |||
| @@ -539,7 +539,7 @@ void ProjucerApplication::handleMainMenuCommand (int menuItemID) | |||
| } | |||
| else if (menuItemID == (codeEditorColourSchemeBaseID + numEditorColourSchemes)) | |||
| { | |||
| AppearanceSettings::showGlobalPreferences (globalPreferencesWindow, true); | |||
| showEditorColourSchemeWindow(); | |||
| } | |||
| else | |||
| { | |||
| @@ -556,7 +556,7 @@ void ProjucerApplication::getAllCommands (Array <CommandID>& commands) | |||
| CommandIDs::open, | |||
| CommandIDs::closeAllDocuments, | |||
| CommandIDs::saveAll, | |||
| CommandIDs::showGlobalPreferences, | |||
| CommandIDs::showGlobalPathsWindow, | |||
| CommandIDs::showUTF8Tool, | |||
| CommandIDs::showSVGPathTool, | |||
| CommandIDs::showAboutWindow, | |||
| @@ -580,9 +580,10 @@ void ProjucerApplication::getCommandInfo (CommandID commandID, ApplicationComman | |||
| result.defaultKeypresses.add (KeyPress ('o', ModifierKeys::commandModifier, 0)); | |||
| break; | |||
| case CommandIDs::showGlobalPreferences: | |||
| result.setInfo ("Preferences...", "Shows the preferences window.", CommandCategories::general, 0); | |||
| result.defaultKeypresses.add (KeyPress (',', ModifierKeys::commandModifier, 0)); | |||
| case CommandIDs::showGlobalPathsWindow: | |||
| result.setInfo ("Global Search Paths...", | |||
| "Shows the window to change the global search paths.", | |||
| CommandCategories::general, 0); | |||
| break; | |||
| case CommandIDs::closeAllDocuments: | |||
| @@ -646,7 +647,7 @@ bool ProjucerApplication::perform (const InvocationInfo& info) | |||
| case CommandIDs::closeAllDocuments: closeAllDocuments (true); break; | |||
| case CommandIDs::showUTF8Tool: showUTF8ToolWindow(); break; | |||
| case CommandIDs::showSVGPathTool: showSVGPathDataToolWindow(); break; | |||
| case CommandIDs::showGlobalPreferences: AppearanceSettings::showGlobalPreferences (globalPreferencesWindow); break; | |||
| case CommandIDs::showGlobalPathsWindow: showPathsWindow(); break; | |||
| case CommandIDs::showAboutWindow: showAboutWindow(); break; | |||
| case CommandIDs::showAppUsageWindow: showApplicationUsageDataAgreementPopup(); break; | |||
| case CommandIDs::loginLogout: doLogout(); break; | |||
| @@ -742,6 +743,32 @@ void ProjucerApplication::dismissApplicationUsageDataAgreementPopup() | |||
| applicationUsageDataWindow = nullptr; | |||
| } | |||
| void ProjucerApplication::showPathsWindow() | |||
| { | |||
| if (pathsWindow != nullptr) | |||
| pathsWindow->toFront (true); | |||
| else | |||
| new FloatingToolWindow ("Global Search Paths", | |||
| "pathsWindowPos", | |||
| new GlobalSearchPathsWindowComponent(), pathsWindow, false, | |||
| 600, 500, 600, 500, 600, 500); | |||
| } | |||
| void ProjucerApplication::showEditorColourSchemeWindow() | |||
| { | |||
| if (editorColourSchemeWindow != nullptr) | |||
| editorColourSchemeWindow->toFront (true); | |||
| else | |||
| { | |||
| new FloatingToolWindow ("Editor Colour Scheme", | |||
| "editorColourSchemeWindowPos", | |||
| new EditorColourSchemeWindowComponent(), | |||
| editorColourSchemeWindow, | |||
| false, | |||
| 500, 500, 500, 500, 500, 500); | |||
| } | |||
| } | |||
| //============================================================================== | |||
| struct FileWithTime | |||
| { | |||
| @@ -846,9 +873,10 @@ void ProjucerApplication::setColourScheme (int index, bool saveSetting) | |||
| if (utf8Window != nullptr) utf8Window->sendLookAndFeelChange(); | |||
| if (svgPathWindow != nullptr) svgPathWindow->sendLookAndFeelChange(); | |||
| if (globalPreferencesWindow != nullptr) globalPreferencesWindow->sendLookAndFeelChange(); | |||
| if (aboutWindow != nullptr) aboutWindow->sendLookAndFeelChange(); | |||
| if (applicationUsageDataWindow != nullptr) applicationUsageDataWindow->sendLookAndFeelChange(); | |||
| if (pathsWindow != nullptr) pathsWindow->sendLookAndFeelChange(); | |||
| if (editorColourSchemeWindow != nullptr) editorColourSchemeWindow->sendLookAndFeelChange(); | |||
| auto* mcm = ModalComponentManager::getInstance(); | |||
| for (auto i = 0; i < mcm->getNumModalComponents(); ++i) | |||
| @@ -102,6 +102,9 @@ public: | |||
| void showApplicationUsageDataAgreementPopup(); | |||
| void dismissApplicationUsageDataAgreementPopup(); | |||
| void showPathsWindow(); | |||
| void showEditorColourSchemeWindow(); | |||
| void updateAllBuildTabs(); | |||
| LatestVersionChecker* createVersionChecker() const; | |||
| @@ -129,8 +132,8 @@ public: | |||
| OpenDocumentManager openDocumentManager; | |||
| ScopedPointer<ApplicationCommandManager> commandManager; | |||
| ScopedPointer<Component> appearanceEditorWindow, globalPreferencesWindow, utf8Window, | |||
| svgPathWindow, aboutWindow, applicationUsageDataWindow; | |||
| ScopedPointer<Component> utf8Window, svgPathWindow, aboutWindow, applicationUsageDataWindow, | |||
| pathsWindow, editorColourSchemeWindow; | |||
| ScopedPointer<FileLogger> logger; | |||
| @@ -745,7 +745,7 @@ void LatestVersionChecker::modalStateFinished (int result, | |||
| void LatestVersionChecker::askUserForLocationToDownload (URL& newVersionToDownload, const String& extraHeaders) | |||
| { | |||
| File targetFolder (findDefaultModulesFolder()); | |||
| File targetFolder (EnabledModuleList::findGlobalModulesFolder()); | |||
| if (isJuceModulesFolder (targetFolder)) | |||
| targetFolder = targetFolder.getParentDirectory(); | |||
| @@ -45,7 +45,7 @@ namespace CommandIDs | |||
| createNewExporter = 0x300015, | |||
| showUTF8Tool = 0x300020, | |||
| showGlobalPreferences = 0x300021, | |||
| showGlobalPathsWindow = 0x300021, | |||
| showTranslationTool = 0x300022, | |||
| showSVGPathTool = 0x300023, | |||
| showAboutWindow = 0x300024, | |||
| @@ -1,465 +0,0 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2017 - ROLI Ltd. | |||
| JUCE is an open source library subject to commercial or open-source | |||
| licensing. | |||
| By using JUCE, you agree to the terms of both the JUCE 5 End-User License | |||
| Agreement and JUCE 5 Privacy Policy (both updated and effective as of the | |||
| 27th April 2017). | |||
| End User License Agreement: www.juce.com/juce-5-licence | |||
| Privacy Policy: www.juce.com/juce-5-privacy-policy | |||
| Or: You may also use this code under the terms of the GPL v3 (see | |||
| www.gnu.org/licenses). | |||
| JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||
| EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||
| DISCLAIMED. | |||
| ============================================================================== | |||
| */ | |||
| #include "../jucer_Headers.h" | |||
| #include "jucer_GlobalPreferences.h" | |||
| #include "../Utility/jucer_FloatingToolWindow.h" | |||
| #include "../Utility/jucer_ColourPropertyComponent.h" | |||
| #include "jucer_Application.h" | |||
| //============================================================================== | |||
| PathSettingsTab::PathSettingsTab (DependencyPathOS os) | |||
| { | |||
| const int maxChars = 1024; | |||
| auto& settings = getAppSettings(); | |||
| vst3PathComponent = pathComponents.add (new TextPropertyComponent (settings.getGlobalPath (Ids::vst3Path, os), "VST3 SDK", maxChars, false)); | |||
| #if ! JUCE_LINUX | |||
| rtasPathComponent = pathComponents.add (new TextPropertyComponent (settings.getGlobalPath (Ids::rtasPath, os), "RTAS SDK", maxChars, false)); | |||
| aaxPathComponent = pathComponents.add (new TextPropertyComponent (settings.getGlobalPath (Ids::aaxPath, os), "AAX SDK", maxChars, false)); | |||
| #endif | |||
| androidSdkPathComponent = pathComponents.add (new TextPropertyComponent (settings.getGlobalPath (Ids::androidSDKPath, os), "Android SDK", maxChars, false)); | |||
| androidNdkPathComponent = pathComponents.add (new TextPropertyComponent (settings.getGlobalPath (Ids::androidNDKPath, os), "Android NDK", maxChars, false)); | |||
| for (auto component : pathComponents) | |||
| { | |||
| addAndMakeVisible (component); | |||
| component->addListener (this); | |||
| textPropertyComponentChanged (component); | |||
| } | |||
| } | |||
| PathSettingsTab::~PathSettingsTab() | |||
| { | |||
| } | |||
| void PathSettingsTab::textPropertyComponentChanged (TextPropertyComponent* textPropertyComponent) | |||
| { | |||
| auto keyName = getKeyForPropertyComponent (textPropertyComponent); | |||
| auto textColour = getAppSettings().isGlobalPathValid (File::getCurrentWorkingDirectory(), keyName, textPropertyComponent->getText()) | |||
| ? findColour (widgetTextColourId) | |||
| : Colours::red; | |||
| textPropertyComponent->setColour (TextPropertyComponent::textColourId, textColour); | |||
| } | |||
| Identifier PathSettingsTab::getKeyForPropertyComponent (TextPropertyComponent* component) const | |||
| { | |||
| if (component == vst3PathComponent) return Ids::vst3Path; | |||
| if (component == rtasPathComponent) return Ids::rtasPath; | |||
| if (component == aaxPathComponent) return Ids::aaxPath; | |||
| if (component == androidSdkPathComponent) return Ids::androidSDKPath; | |||
| if (component == androidNdkPathComponent) return Ids::androidNDKPath; | |||
| // this property component does not have a key associated to it! | |||
| jassertfalse; | |||
| return {}; | |||
| } | |||
| Component* PathSettingsTab::getContent() | |||
| { | |||
| return this; | |||
| } | |||
| String PathSettingsTab::getName() const noexcept | |||
| { | |||
| return "Paths"; | |||
| } | |||
| void PathSettingsTab::resized() | |||
| { | |||
| const int componentHeight = 25; | |||
| for (auto component : pathComponents) | |||
| { | |||
| const auto elementNumber = pathComponents.indexOf (component); | |||
| component->setBounds (10, componentHeight * elementNumber, getWidth() - 20, componentHeight); | |||
| } | |||
| } | |||
| void PathSettingsTab::lookAndFeelChanged() | |||
| { | |||
| for (auto* comp : pathComponents) | |||
| textPropertyComponentChanged (comp); | |||
| } | |||
| //============================================================================== | |||
| struct AppearanceEditor | |||
| { | |||
| struct FontScanPanel : public Component, | |||
| private Timer | |||
| { | |||
| FontScanPanel() | |||
| { | |||
| fontsToScan = Font::findAllTypefaceNames(); | |||
| startTimer (1); | |||
| } | |||
| void paint (Graphics& g) override | |||
| { | |||
| g.fillAll (findColour (backgroundColourId)); | |||
| g.setFont (14.0f); | |||
| g.setColour (findColour (defaultTextColourId)); | |||
| g.drawFittedText ("Scanning for fonts..", getLocalBounds(), Justification::centred, 2); | |||
| const auto size = 30; | |||
| getLookAndFeel().drawSpinningWaitAnimation (g, Colours::white, (getWidth() - size) / 2, getHeight() / 2 - 50, size, size); | |||
| } | |||
| void timerCallback() override | |||
| { | |||
| repaint(); | |||
| if (fontsToScan.size() == 0) | |||
| { | |||
| getAppSettings().monospacedFontNames = fontsFound; | |||
| if (auto* tab = findParentComponentOfClass<AppearanceSettingsTab>()) | |||
| tab->changeContent (new EditorPanel()); | |||
| } | |||
| else | |||
| { | |||
| if (isMonospacedTypeface (fontsToScan[0])) | |||
| fontsFound.add (fontsToScan[0]); | |||
| fontsToScan.remove (0); | |||
| } | |||
| } | |||
| // A rather hacky trick to select only the fixed-pitch fonts.. | |||
| // This is unfortunately a bit slow, but will work on all platforms. | |||
| static bool isMonospacedTypeface (const String& name) | |||
| { | |||
| const Font font (name, 20.0f, Font::plain); | |||
| const auto width = font.getStringWidth ("...."); | |||
| return width == font.getStringWidth ("WWWW") | |||
| && width == font.getStringWidth ("0000") | |||
| && width == font.getStringWidth ("1111") | |||
| && width == font.getStringWidth ("iiii"); | |||
| } | |||
| StringArray fontsToScan, fontsFound; | |||
| }; | |||
| //============================================================================== | |||
| struct EditorPanel : public Component, | |||
| private ButtonListener | |||
| { | |||
| EditorPanel() | |||
| : loadButton ("Load Scheme..."), | |||
| saveButton ("Save Scheme...") | |||
| { | |||
| rebuildProperties(); | |||
| addAndMakeVisible (panel); | |||
| addAndMakeVisible (loadButton); | |||
| addAndMakeVisible (saveButton); | |||
| loadButton.addListener (this); | |||
| saveButton.addListener (this); | |||
| lookAndFeelChanged(); | |||
| saveSchemeState(); | |||
| } | |||
| ~EditorPanel() | |||
| { | |||
| if (hasSchemeBeenModifiedSinceSave()) | |||
| saveScheme (true); | |||
| } | |||
| void rebuildProperties() | |||
| { | |||
| auto& scheme = getAppSettings().appearance; | |||
| Array<PropertyComponent*> props; | |||
| auto fontValue = scheme.getCodeFontValue(); | |||
| props.add (FontNameValueSource::createProperty ("Code Editor Font", fontValue)); | |||
| props.add (FontSizeValueSource::createProperty ("Font Size", fontValue)); | |||
| const auto colourNames = scheme.getColourNames(); | |||
| for (int i = 0; i < colourNames.size(); ++i) | |||
| props.add (new ColourPropertyComponent (nullptr, colourNames[i], | |||
| scheme.getColourValue (colourNames[i]), | |||
| Colours::white, false)); | |||
| panel.clear(); | |||
| panel.addProperties (props); | |||
| } | |||
| void resized() override | |||
| { | |||
| auto r = getLocalBounds(); | |||
| panel.setBounds (r.removeFromTop (getHeight() - 28).reduced (10, 2)); | |||
| loadButton.setBounds (r.removeFromLeft (getWidth() / 2).reduced (10, 1)); | |||
| saveButton.setBounds (r.reduced (10, 1)); | |||
| } | |||
| private: | |||
| PropertyPanel panel; | |||
| TextButton loadButton, saveButton; | |||
| Font codeFont; | |||
| Array<var> colourValues; | |||
| void buttonClicked (Button* b) override | |||
| { | |||
| if (b == &loadButton) | |||
| loadScheme(); | |||
| else | |||
| saveScheme (false); | |||
| } | |||
| void saveScheme (bool isExit) | |||
| { | |||
| FileChooser fc ("Select a file in which to save this colour-scheme...", | |||
| getAppSettings().appearance.getSchemesFolder() | |||
| .getNonexistentChildFile ("Scheme", AppearanceSettings::getSchemeFileSuffix()), | |||
| AppearanceSettings::getSchemeFileWildCard()); | |||
| if (fc.browseForFileToSave (true)) | |||
| { | |||
| File file (fc.getResult().withFileExtension (AppearanceSettings::getSchemeFileSuffix())); | |||
| getAppSettings().appearance.writeToFile (file); | |||
| getAppSettings().appearance.refreshPresetSchemeList(); | |||
| saveSchemeState(); | |||
| ProjucerApplication::getApp().selectEditorColourSchemeWithName (file.getFileNameWithoutExtension()); | |||
| } | |||
| else if (isExit) | |||
| { | |||
| restorePreviousScheme(); | |||
| } | |||
| } | |||
| void loadScheme() | |||
| { | |||
| FileChooser fc ("Please select a colour-scheme file to load...", | |||
| getAppSettings().appearance.getSchemesFolder(), | |||
| AppearanceSettings::getSchemeFileWildCard()); | |||
| if (fc.browseForFileToOpen()) | |||
| { | |||
| if (getAppSettings().appearance.readFromFile (fc.getResult())) | |||
| { | |||
| rebuildProperties(); | |||
| saveSchemeState(); | |||
| } | |||
| } | |||
| } | |||
| void lookAndFeelChanged() override | |||
| { | |||
| loadButton.setColour (TextButton::buttonColourId, | |||
| findColour (secondaryButtonBackgroundColourId)); | |||
| } | |||
| void saveSchemeState() | |||
| { | |||
| auto& appearance = getAppSettings().appearance; | |||
| const auto colourNames = appearance.getColourNames(); | |||
| codeFont = appearance.getCodeFont(); | |||
| colourValues.clear(); | |||
| for (int i = 0; i < colourNames.size(); ++i) | |||
| colourValues.add (appearance.getColourValue (colourNames[i]).getValue()); | |||
| } | |||
| bool hasSchemeBeenModifiedSinceSave() | |||
| { | |||
| auto& appearance = getAppSettings().appearance; | |||
| const auto colourNames = appearance.getColourNames(); | |||
| if (codeFont != appearance.getCodeFont()) | |||
| return true; | |||
| for (int i = 0; i < colourNames.size(); ++i) | |||
| if (colourValues[i] != appearance.getColourValue (colourNames[i]).getValue()) | |||
| return true; | |||
| return false; | |||
| } | |||
| void restorePreviousScheme() | |||
| { | |||
| auto& appearance = getAppSettings().appearance; | |||
| const auto colourNames = appearance.getColourNames(); | |||
| appearance.getCodeFontValue().setValue (codeFont.toString()); | |||
| for (int i = 0; i < colourNames.size(); ++i) | |||
| appearance.getColourValue (colourNames[i]).setValue (colourValues[i]); | |||
| } | |||
| JUCE_DECLARE_NON_COPYABLE (EditorPanel) | |||
| }; | |||
| //============================================================================== | |||
| struct FontNameValueSource : public ValueSourceFilter | |||
| { | |||
| FontNameValueSource (const Value& source) : ValueSourceFilter (source) {} | |||
| var getValue() const override | |||
| { | |||
| return Font::fromString (sourceValue.toString()).getTypefaceName(); | |||
| } | |||
| void setValue (const var& newValue) override | |||
| { | |||
| auto font = Font::fromString (sourceValue.toString()); | |||
| font.setTypefaceName (newValue.toString().isEmpty() ? Font::getDefaultMonospacedFontName() | |||
| : newValue.toString()); | |||
| sourceValue = font.toString(); | |||
| } | |||
| static ChoicePropertyComponent* createProperty (const String& title, const Value& value) | |||
| { | |||
| auto fontNames = getAppSettings().monospacedFontNames; | |||
| Array<var> values; | |||
| values.add (Font::getDefaultMonospacedFontName()); | |||
| values.add (var()); | |||
| for (int i = 0; i < fontNames.size(); ++i) | |||
| values.add (fontNames[i]); | |||
| StringArray names; | |||
| names.add ("<Default Monospaced>"); | |||
| names.add (String()); | |||
| names.addArray (getAppSettings().monospacedFontNames); | |||
| return new ChoicePropertyComponent (Value (new FontNameValueSource (value)), | |||
| title, names, values); | |||
| } | |||
| }; | |||
| //============================================================================== | |||
| struct FontSizeValueSource : public ValueSourceFilter | |||
| { | |||
| FontSizeValueSource (const Value& source) : ValueSourceFilter (source) {} | |||
| var getValue() const override | |||
| { | |||
| return Font::fromString (sourceValue.toString()).getHeight(); | |||
| } | |||
| void setValue (const var& newValue) override | |||
| { | |||
| sourceValue = Font::fromString (sourceValue.toString()).withHeight (newValue).toString(); | |||
| } | |||
| static PropertyComponent* createProperty (const String& title, const Value& value) | |||
| { | |||
| return new SliderPropertyComponent (Value (new FontSizeValueSource (value)), | |||
| title, 5.0, 40.0, 0.1, 0.5); | |||
| } | |||
| }; | |||
| }; | |||
| void AppearanceSettings::showGlobalPreferences (ScopedPointer<Component>& ownerPointer, bool showCodeEditorTab) | |||
| { | |||
| if (ownerPointer != nullptr) | |||
| ownerPointer->toFront (true); | |||
| else | |||
| { | |||
| auto* prefs = new GlobalPreferencesComponent(); | |||
| new FloatingToolWindow ("Preferences", | |||
| "globalPreferencesEditorPos", | |||
| prefs, | |||
| ownerPointer, false, | |||
| 500, 500, 500, 500, 500, 500); | |||
| if (showCodeEditorTab) | |||
| prefs->setCurrentTabIndex (1); | |||
| } | |||
| } | |||
| //============================================================================== | |||
| AppearanceSettingsTab::AppearanceSettingsTab() | |||
| { | |||
| if (getAppSettings().monospacedFontNames.size() == 0) | |||
| content = new AppearanceEditor::FontScanPanel(); | |||
| else | |||
| content = new AppearanceEditor::EditorPanel(); | |||
| changeContent (content); | |||
| } | |||
| Component* AppearanceSettingsTab::getContent() | |||
| { | |||
| return this; | |||
| } | |||
| void AppearanceSettingsTab::changeContent (Component* newContent) | |||
| { | |||
| content = newContent; | |||
| addAndMakeVisible (content); | |||
| content->setBounds (getLocalBounds()); | |||
| } | |||
| String AppearanceSettingsTab::getName() const noexcept | |||
| { | |||
| return "Code Editor"; | |||
| } | |||
| void AppearanceSettingsTab::resized() | |||
| { | |||
| content->setBounds (getLocalBounds()); | |||
| } | |||
| //============================================================================== | |||
| GlobalPreferencesComponent::GlobalPreferencesComponent() | |||
| : TabbedComponent (TabbedButtonBar::TabsAtTop) | |||
| { | |||
| preferenceTabs.add (new PathSettingsTab (TargetOS::getThisOS())); | |||
| preferenceTabs.add (new AppearanceSettingsTab); | |||
| for (GlobalPreferencesTab** tab = preferenceTabs.begin(); tab != preferenceTabs.end(); ++tab) | |||
| addTab ((*tab)->getName(), findColour (backgroundColourId, true), (*tab)->getContent(), true); | |||
| } | |||
| void GlobalPreferencesComponent::paint (Graphics& g) | |||
| { | |||
| g.fillAll (findColour (backgroundColourId)); | |||
| } | |||
| void GlobalPreferencesComponent::lookAndFeelChanged() | |||
| { | |||
| for (auto* tab : preferenceTabs) | |||
| tab->getContent()->sendLookAndFeelChange(); | |||
| } | |||
| @@ -1,116 +0,0 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2017 - ROLI Ltd. | |||
| JUCE is an open source library subject to commercial or open-source | |||
| licensing. | |||
| By using JUCE, you agree to the terms of both the JUCE 5 End-User License | |||
| Agreement and JUCE 5 Privacy Policy (both updated and effective as of the | |||
| 27th April 2017). | |||
| End User License Agreement: www.juce.com/juce-5-licence | |||
| Privacy Policy: www.juce.com/juce-5-privacy-policy | |||
| Or: You may also use this code under the terms of the GPL v3 (see | |||
| www.gnu.org/licenses). | |||
| JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||
| EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||
| DISCLAIMED. | |||
| ============================================================================== | |||
| */ | |||
| #pragma once | |||
| //============================================================================== | |||
| #include "../Project/jucer_DependencyPathPropertyComponent.h" | |||
| class GlobalPreferencesTab | |||
| { | |||
| public: | |||
| virtual ~GlobalPreferencesTab() {} | |||
| virtual Component* getContent() = 0; | |||
| virtual String getName() const noexcept = 0; | |||
| }; | |||
| //============================================================================== | |||
| /** This component implements the "Paths" tab in the global preferences window, | |||
| which defines the default paths for dependencies like third-party SDKs | |||
| for this machine. | |||
| */ | |||
| class PathSettingsTab : public GlobalPreferencesTab, | |||
| public Component, | |||
| private TextPropertyComponent::Listener | |||
| { | |||
| public: | |||
| PathSettingsTab (DependencyPathOS); | |||
| ~PathSettingsTab(); | |||
| Component* getContent() override; | |||
| String getName() const noexcept override; | |||
| void resized() override; | |||
| private: | |||
| void textPropertyComponentChanged (TextPropertyComponent*) override; | |||
| Identifier getKeyForPropertyComponent (TextPropertyComponent*) const; | |||
| void lookAndFeelChanged() override; | |||
| OwnedArray<TextPropertyComponent> pathComponents; | |||
| TextPropertyComponent* vst3PathComponent; | |||
| TextPropertyComponent* rtasPathComponent; | |||
| TextPropertyComponent* aaxPathComponent; | |||
| TextPropertyComponent* androidSdkPathComponent; | |||
| TextPropertyComponent* androidNdkPathComponent; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PathSettingsTab) | |||
| }; | |||
| //============================================================================== | |||
| /** This component implements the "Code Editor" tab in the global preferences window, | |||
| which sets font sizes and colours for the Projucer's code editor. | |||
| The content is either an EditorPanel (the actual settings tab) or a FontScanPanel | |||
| (shown if the tab is scanning for available fonts before showing the EditorPanel). | |||
| */ | |||
| class AppearanceSettingsTab : public GlobalPreferencesTab, | |||
| public Component | |||
| { | |||
| public: | |||
| AppearanceSettingsTab(); | |||
| Component* getContent() override; | |||
| void changeContent (Component* newContent); | |||
| String getName() const noexcept override; | |||
| void resized() override; | |||
| private: | |||
| ScopedPointer<Component> content; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AppearanceSettingsTab) | |||
| }; | |||
| //============================================================================== | |||
| class GlobalPreferencesComponent : public TabbedComponent | |||
| { | |||
| public: | |||
| GlobalPreferencesComponent(); | |||
| void paint (Graphics&) override; | |||
| private: | |||
| void lookAndFeelChanged() override; | |||
| OwnedArray<GlobalPreferencesTab> preferenceTabs; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GlobalPreferencesComponent) | |||
| }; | |||
| @@ -35,6 +35,8 @@ | |||
| #include "../Utility/jucer_SVGPathDataComponent.h" | |||
| #include "../Utility/jucer_AboutWindowComponent.h" | |||
| #include "../Utility/jucer_ApplicationUsageDataWindowComponent.h" | |||
| #include "../Utility/jucer_EditorColourSchemeWindowComponent.h" | |||
| #include "../Utility/jucer_GlobalSearchPathsWindowComponent.h" | |||
| #include "../Utility/jucer_FloatingToolWindow.h" | |||
| #include "../LiveBuildEngine/projucer_MessageIDs.h" | |||
| @@ -580,39 +580,3 @@ Project* MainWindowList::getFrontmostProject() | |||
| return nullptr; | |||
| } | |||
| File findDefaultModulesFolder (bool mustContainJuceCoreModule) | |||
| { | |||
| auto& windows = ProjucerApplication::getApp().mainWindowList; | |||
| for (int i = windows.windows.size(); --i >= 0;) | |||
| { | |||
| if (auto* p = windows.windows.getUnchecked (i)->getProject()) | |||
| { | |||
| const File f (EnabledModuleList::findDefaultModulesFolder (*p)); | |||
| if (isJuceModulesFolder (f) || (f.isDirectory() && ! mustContainJuceCoreModule)) | |||
| return f; | |||
| } | |||
| } | |||
| if (mustContainJuceCoreModule) | |||
| return findDefaultModulesFolder (false); | |||
| auto f = File::getSpecialLocation (File::currentApplicationFile); | |||
| for (;;) | |||
| { | |||
| auto parent = f.getParentDirectory(); | |||
| if (parent == f || ! parent.isDirectory()) | |||
| break; | |||
| if (isJuceFolder (parent)) | |||
| return parent.getChildFile ("modules"); | |||
| f = parent; | |||
| } | |||
| return {}; | |||
| } | |||
| @@ -26,7 +26,6 @@ | |||
| #include "../../jucer_Headers.h" | |||
| #include "../../Application/jucer_AppearanceSettings.h" | |||
| #include "../../Application/jucer_GlobalPreferences.h" | |||
| #include "../../Application/jucer_Application.h" | |||
| #include "jucer_JucerDocumentEditor.h" | |||
| #include "jucer_TestComponent.h" | |||
| @@ -519,9 +519,7 @@ private: | |||
| paths.addArray (getSearchPathsFromString (ProjectProperties::getSystemHeaderPathString (project))); | |||
| if (project.getProjectType().isAudioPlugin()) | |||
| { | |||
| paths.add (getAppSettings().getGlobalPath (Ids::vst3Path, TargetOS::getThisOS()).toString()); | |||
| } | |||
| paths.add (getAppSettings().getStoredPath (Ids::vst3Path).toString()); | |||
| OwnedArray<LibraryModule> modules; | |||
| project.getModules().createRequiredModules (modules); | |||
| @@ -493,8 +493,26 @@ Value ProjectExporter::getPathForModuleValue (const String& moduleID) | |||
| String ProjectExporter::getPathForModuleString (const String& moduleID) const | |||
| { | |||
| return settings.getChildWithName (Ids::MODULEPATHS) | |||
| .getChildWithProperty (Ids::ID, moduleID) [Ids::path].toString(); | |||
| auto exporterPath = settings.getChildWithName (Ids::MODULEPATHS) | |||
| .getChildWithProperty (Ids::ID, moduleID) [Ids::path].toString(); | |||
| if (exporterPath.isEmpty() || project.getModules().shouldUseGlobalPath (moduleID).getValue()) | |||
| { | |||
| auto id = EnabledModuleList::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 EnabledModuleList::findUserModuleFolder (moduleID, | |||
| getAppSettings().getStoredPath (Ids::defaultUserModulePath).toString(), | |||
| project).getFullPathName(); | |||
| } | |||
| return exporterPath; | |||
| } | |||
| void ProjectExporter::removePathForModule (const String& moduleID) | |||
| @@ -504,6 +522,18 @@ void ProjectExporter::removePathForModule (const String& moduleID) | |||
| paths.removeChild (m, project.getUndoManagerFor (settings)); | |||
| } | |||
| TargetOS::OS ProjectExporter::getTargetOSForExporter() const | |||
| { | |||
| auto targetOS = TargetOS::unknown; | |||
| if (isWindows()) targetOS = TargetOS::windows; | |||
| else if (isOSX() || isiOS()) targetOS = TargetOS::osx; | |||
| else if (isLinux()) targetOS = TargetOS::linux; | |||
| else if (isAndroid()) targetOS = TargetOS::getThisOS(); | |||
| return targetOS; | |||
| } | |||
| RelativePath ProjectExporter::getModuleFolderRelativeToProject (const String& moduleID) const | |||
| { | |||
| if (project.getModules().shouldCopyModuleFilesLocally (moduleID).getValue()) | |||
| @@ -28,7 +28,7 @@ | |||
| #include "../Project/jucer_Project.h" | |||
| #include "../Project/jucer_ProjectType.h" | |||
| #include "../Application/jucer_GlobalPreferences.h" | |||
| #include "../Project/jucer_DependencyPathPropertyComponent.h" | |||
| class ProjectSaver; | |||
| @@ -160,6 +160,8 @@ public: | |||
| String getPathForModuleString (const String& moduleID) const; | |||
| void removePathForModule (const String& moduleID); | |||
| TargetOS::OS getTargetOSForExporter() const; | |||
| RelativePath getLegacyModulePath (const String& moduleID) const; | |||
| String getLegacyModulePath() const; | |||
| @@ -28,24 +28,11 @@ | |||
| class InfoButton : public Button | |||
| { | |||
| public: | |||
| InfoButton (PropertyComponent& comp) | |||
| : Button (String()), | |||
| associatedComponent (comp) | |||
| InfoButton (const String& infoToDisplay = String()) | |||
| : Button (String()) | |||
| { | |||
| tooltip = associatedComponent.getTooltip(); | |||
| auto stringWidth = Font (14.0f).getStringWidthFloat (tooltip); | |||
| int maxWidth = 300; | |||
| if (stringWidth > maxWidth) | |||
| { | |||
| width = maxWidth; | |||
| numLines += static_cast<int> (stringWidth / width); | |||
| } | |||
| else | |||
| { | |||
| width = roundToInt (stringWidth); | |||
| } | |||
| if (infoToDisplay.isNotEmpty()) | |||
| setInfoToDisplay (infoToDisplay); | |||
| } | |||
| void paintButton (Graphics& g, bool isMouseOverButton, bool isButtonDown) override | |||
| @@ -64,23 +51,38 @@ public: | |||
| void clicked() override | |||
| { | |||
| auto* w = new InfoWindow (tooltip); | |||
| auto* w = new InfoWindow (info); | |||
| w->setSize (width, w->getHeight() * numLines + 10); | |||
| CallOutBox::launchAsynchronously (w, getScreenBounds(), nullptr); | |||
| } | |||
| PropertyComponent& associatedComponent; | |||
| void setInfoToDisplay (const String& infoToDisplay) | |||
| { | |||
| if (infoToDisplay.isNotEmpty()) | |||
| { | |||
| info = infoToDisplay; | |||
| auto stringWidth = roundToInt (Font (14.0f).getStringWidthFloat (info)); | |||
| width = jmin (300, stringWidth); | |||
| numLines += static_cast<int> (stringWidth / width); | |||
| } | |||
| } | |||
| void setAssociatedComponent (Component* comp) { associatedComponent = comp; } | |||
| Component* getAssociatedComponent() { return associatedComponent; } | |||
| private: | |||
| String tooltip; | |||
| String info; | |||
| Component* associatedComponent = nullptr; | |||
| int width; | |||
| int numLines = 1; | |||
| //============================================================================== | |||
| struct InfoWindow : public Component | |||
| { | |||
| InfoWindow (String s) | |||
| InfoWindow (const String& s) | |||
| : stringToDisplay (s) | |||
| { | |||
| setSize (150, 14); | |||
| @@ -125,7 +127,8 @@ public: | |||
| if (! prop->getTooltip().isEmpty()) | |||
| { | |||
| addAndMakeVisible (infoButtons.add (new InfoButton (*prop))); | |||
| addAndMakeVisible (infoButtons.add (new InfoButton (prop->getTooltip()))); | |||
| infoButtons.getLast()->setAssociatedComponent (prop); | |||
| prop->setTooltip (String()); // set the tooltip to empty so it only displays when its button is clicked | |||
| } | |||
| } | |||
| @@ -145,7 +148,7 @@ public: | |||
| InfoButton* buttonToUse = nullptr; | |||
| for (auto* b : infoButtons) | |||
| if (&b->associatedComponent == pp) | |||
| if (b->getAssociatedComponent() == pp) | |||
| buttonToUse = b; | |||
| if (buttonToUse != nullptr) | |||
| @@ -189,11 +192,12 @@ public: | |||
| if (pp->getName() == "Dependencies") | |||
| return; | |||
| if (auto* propertyChild = pp->getChildComponent (0)) | |||
| for (int i = pp->getNumChildComponents() - 1; i >= 0; --i) | |||
| { | |||
| auto bounds = propertyChild->getBounds(); | |||
| auto* child = pp->getChildComponent (i); | |||
| propertyChild->setBounds (bounds.withSizeKeepingCentre (propertyChild->getWidth(), pp->getPreferredHeight())); | |||
| auto bounds = child->getBounds(); | |||
| child->setBounds (bounds.withSizeKeepingCentre (child->getWidth(), pp->getPreferredHeight())); | |||
| } | |||
| } | |||
| @@ -30,12 +30,16 @@ public: | |||
| ModuleItem (Project& p, const String& modID) | |||
| : project (p), moduleID (modID) | |||
| { | |||
| auto moduleVersionNum = project.getModules().getModuleInfo (moduleID).getVersion(); | |||
| if (moduleVersionNum != ProjucerApplication::getApp().getApplicationVersion()) | |||
| moduleVersion = moduleVersionNum; | |||
| } | |||
| bool canBeSelected() const override { return true; } | |||
| bool mightContainSubItems() override { return false; } | |||
| String getUniqueName() const override { return "module_" + moduleID; } | |||
| String getDisplayName() const override { return moduleID; } | |||
| String getDisplayName() const override { return moduleID + (moduleVersion.isNotEmpty() ? String (" (" + moduleVersion + ")") : ""); } | |||
| String getRenamingName() const override { return getDisplayName(); } | |||
| void setName (const String&) override {} | |||
| bool isMissing() const override { return hasMissingDependencies(); } | |||
| @@ -86,6 +90,7 @@ public: | |||
| Project& project; | |||
| String moduleID; | |||
| String moduleVersion; | |||
| private: | |||
| bool hasMissingDependencies() const | |||
| @@ -94,7 +99,8 @@ private: | |||
| } | |||
| //============================================================================== | |||
| class ModuleSettingsPanel : public Component | |||
| class ModuleSettingsPanel : public Component, | |||
| private Value::Listener | |||
| { | |||
| public: | |||
| ModuleSettingsPanel (Project& p, const String& modID) | |||
| @@ -102,37 +108,72 @@ private: | |||
| project (p), | |||
| moduleID (modID) | |||
| { | |||
| defaultJuceModulePathValue.referTo (getAppSettings().getStoredPath (Ids::defaultJuceModulePath)); | |||
| defaultUserModulePathValue.referTo (getAppSettings().getStoredPath (Ids::defaultUserModulePath)); | |||
| defaultJuceModulePathValue.addListener (this); | |||
| defaultUserModulePathValue.addListener (this); | |||
| addAndMakeVisible (group); | |||
| refresh(); | |||
| } | |||
| void refresh() | |||
| { | |||
| setEnabled (project.getModules().isModuleEnabled (moduleID)); | |||
| auto& modules = project.getModules(); | |||
| const auto& isUsingGlobalPathValue = modules.shouldUseGlobalPath (moduleID); | |||
| setEnabled (modules.isModuleEnabled (moduleID)); | |||
| PropertyListBuilder props; | |||
| props.add (new ModuleInfoComponent (project, moduleID)); | |||
| if (project.getModules().getExtraDependenciesNeeded (moduleID).size() > 0) | |||
| if (modules.getExtraDependenciesNeeded (moduleID).size() > 0) | |||
| props.add (new MissingDependenciesComponent (project, moduleID)); | |||
| modulePathValueSources.clear(); | |||
| for (Project::ExporterIterator exporter (project); exporter.next();) | |||
| props.add (new FilePathPropertyComponent (exporter->getPathForModuleValue (moduleID), | |||
| "Path for " + exporter->getName().quoted(), | |||
| true, "*", project.getProjectFolder()), | |||
| { | |||
| auto key = modules.isJuceModule (moduleID) ? Ids::defaultJuceModulePath | |||
| : Ids::defaultUserModulePath; | |||
| Value src (modulePathValueSources.add (new DependencyPathValueSource (exporter->getPathForModuleValue (moduleID), | |||
| key, exporter->getTargetOSForExporter()))); | |||
| auto* pathComponent = new DependencyFilePathPropertyComponent (src, "Path for " + exporter->getName().quoted(), | |||
| true, "*", project.getProjectFolder()); | |||
| props.add (pathComponent, | |||
| "A path to the folder that contains the " + moduleID + " module when compiling the " | |||
| + exporter->getName().quoted() + " target. " | |||
| + exporter->getName().quoted() + " target. " | |||
| "This can be an absolute path, or relative to the jucer project folder, but it " | |||
| "must be valid on the filesystem of the target machine that will be performing this build."); | |||
| "must be valid on the filesystem of the target machine that will be performing this build. If this " | |||
| "is empty then the global path will be used."); | |||
| props.add (new BooleanPropertyComponent (project.getModules().shouldCopyModuleFilesLocally (moduleID), | |||
| pathComponent->setEnabled (! isUsingGlobalPathValue.getValue()); | |||
| } | |||
| globalPathValue.referTo (isUsingGlobalPathValue); | |||
| auto menuItemString = (TargetOS::getThisOS() == TargetOS::osx ? "\"Projucer->Global Search Paths...\"" | |||
| : "\"File->Global Search Paths...\""); | |||
| props.add (new BooleanPropertyComponent (globalPathValue, | |||
| "Use global path", "Use global path for this module"), | |||
| 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"), | |||
| "If this is enabled, then a local copy of the entire module will be made inside your project (in the auto-generated JuceLibraryFiles folder), " | |||
| "so that your project will be self-contained, and won't need to contain any references to files in other folders. " | |||
| "This also means that you can check the module into your source-control system to make sure it is always in sync with your own code."); | |||
| props.add (new BooleanPropertyComponent (project.getModules().shouldShowAllModuleFilesInProject (moduleID), | |||
| props.add (new BooleanPropertyComponent (modules.shouldShowAllModuleFilesInProject (moduleID), | |||
| "Add source to project", "Make module files browsable in projects"), | |||
| "If this is enabled, then the entire source tree from this module will be shown inside your project, " | |||
| "making it easy to browse/edit the module's classes. If disabled, then only the minimum number of files " | |||
| @@ -148,7 +189,7 @@ private: | |||
| mappings.add (Project::configFlagEnabled); | |||
| mappings.add (Project::configFlagDisabled); | |||
| ModuleDescription info (project.getModules().getModuleInfo (moduleID)); | |||
| ModuleDescription info (modules.getModuleInfo (moduleID)); | |||
| if (info.isValid()) | |||
| { | |||
| @@ -177,6 +218,28 @@ private: | |||
| PropertyGroupComponent group; | |||
| Project& project; | |||
| String moduleID; | |||
| Value globalPathValue; | |||
| Value defaultJuceModulePathValue, defaultUserModulePathValue; | |||
| 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); | |||
| } | |||
| } | |||
| if (auto* moduleInfo = dynamic_cast<ModuleInfoComponent*> (group.properties.getUnchecked (0))) | |||
| moduleInfo->refresh(); | |||
| } | |||
| //============================================================================== | |||
| class ModuleInfoComponent : public PropertyComponent, | |||
| @@ -193,13 +256,13 @@ private: | |||
| refresh(); | |||
| } | |||
| private: | |||
| void refresh() override | |||
| { | |||
| info = project.getModules().getModuleInfo (moduleID); | |||
| repaint(); | |||
| } | |||
| private: | |||
| void paint (Graphics& g) override | |||
| { | |||
| auto bounds = getLocalBounds().reduced (10); | |||
| @@ -207,15 +270,17 @@ private: | |||
| if (info.isValid()) | |||
| { | |||
| auto topSlice = bounds.removeFromTop (bounds.getHeight() / 3); | |||
| auto topSlice = bounds.removeFromTop (bounds.getHeight() / 2); | |||
| bounds.removeFromTop (bounds.getHeight() / 6); | |||
| auto bottomSlice = bounds; | |||
| g.setColour (findColour (defaultTextColourId)); | |||
| g.drawFittedText (info.getName(), topSlice.removeFromTop (topSlice.getHeight() / 3), Justification::centredLeft, 1); | |||
| g.drawFittedText ("Version: " + info.getVersion(), topSlice.removeFromTop (topSlice.getHeight() / 2), Justification::centredLeft, 1); | |||
| g.drawFittedText ("License: " + info.getLicense(), topSlice.removeFromTop (topSlice.getHeight()), Justification::centredLeft, 1); | |||
| g.drawFittedText (info.getName(), topSlice.removeFromTop (topSlice.getHeight() / 4), Justification::centredLeft, 1); | |||
| g.drawFittedText ("Version: " + info.getVersion(), topSlice.removeFromTop (topSlice.getHeight() / 3), Justification::centredLeft, 1); | |||
| g.drawFittedText ("License: " + info.getLicense(), topSlice.removeFromTop (topSlice.getHeight() / 2), Justification::centredLeft, 1); | |||
| g.drawFittedText ("Location: " + info.getFolder().getParentDirectory().getFullPathName(), | |||
| topSlice.removeFromTop (topSlice.getHeight()), Justification::centredLeft, 1); | |||
| g.drawFittedText (info.getDescription(), bottomSlice, Justification::topLeft, 3, 1.0f); | |||
| } | |||
| @@ -270,23 +335,22 @@ private: | |||
| void buttonClicked (Button*) override | |||
| { | |||
| bool anyFailed = false; | |||
| ModuleList list; | |||
| list.scanAllKnownFolders (project); | |||
| for (int i = missingDependencies.size(); --i >= 0;) | |||
| { | |||
| if (const ModuleDescription* info = list.getModuleWithID (missingDependencies[i])) | |||
| project.getModules().addModule (info->moduleFolder, project.getModules().areMostModulesCopiedLocally()); | |||
| else | |||
| anyFailed = true; | |||
| } | |||
| list.scanGlobalJuceModulePath(); | |||
| if (! tryToFix (list)) | |||
| list.scanGlobalUserModulePath(); | |||
| if (! tryToFix (list)) | |||
| list.scanProjectExporterModulePaths (project); | |||
| bool fixed = tryToFix (list); | |||
| if (ModuleSettingsPanel* p = findParentComponentOfClass<ModuleSettingsPanel>()) | |||
| p->refresh(); | |||
| if (anyFailed) | |||
| if (! fixed) | |||
| AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
| "Adding Missing Dependencies", | |||
| "Couldn't locate some of these modules - you'll need to find their " | |||
| @@ -304,6 +368,26 @@ private: | |||
| StringArray missingDependencies; | |||
| TextButton fixButton; | |||
| bool tryToFix (ModuleList& list) | |||
| { | |||
| auto& modules = project.getModules(); | |||
| auto copyLocally = modules.areMostModulesCopiedLocally(); | |||
| auto useGlobalPath = modules.areMostModulesUsingGlobalPath(); | |||
| StringArray missing; | |||
| for (auto missingModule : missingDependencies) | |||
| { | |||
| if (auto* info = list.getModuleWithID (missingModule)) | |||
| modules.addModule (info->moduleFolder, copyLocally, useGlobalPath); | |||
| else | |||
| missing.add (missingModule); | |||
| } | |||
| missingDependencies.swapWith (missing); | |||
| return (missingDependencies.size() == 0); | |||
| } | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MissingDependenciesComponent) | |||
| }; | |||
| }; | |||
| @@ -370,7 +454,8 @@ public: | |||
| for (int i = 0; i < modules.size(); ++i) | |||
| project.getModules().addModule (modules.getReference(i).moduleFolder, | |||
| project.getModules().areMostModulesCopiedLocally()); | |||
| project.getModules().areMostModulesCopiedLocally(), | |||
| project.getModules().areMostModulesUsingGlobalPath()); | |||
| } | |||
| void addSubItems() override | |||
| @@ -381,12 +466,36 @@ public: | |||
| void showPopupMenu() override | |||
| { | |||
| PopupMenu menu, knownModules, copyModeMenu; | |||
| auto& modules = project.getModules(); | |||
| PopupMenu knownModules, jucePathModules, userPathModules, exporterPathsModules; | |||
| const StringArray modules (getAvailableModules()); | |||
| for (int i = 0; i < modules.size(); ++i) | |||
| knownModules.addItem (1 + i, modules[i], ! project.getModules().isModuleEnabled (modules[i])); | |||
| auto index = 100; | |||
| auto globalJucePathModules = getAvailableModulesInGlobalJucePath(); | |||
| for (auto m : globalJucePathModules) | |||
| jucePathModules.addItem (index++, m, ! modules.isModuleEnabled (m)); | |||
| knownModules.addSubMenu ("Global JUCE modules path", jucePathModules); | |||
| index = 200; | |||
| auto globalUserPathModules = getAvailableModulesInGlobalUserPath(); | |||
| for (auto m : getAvailableModulesInGlobalUserPath()) | |||
| { | |||
| if (! globalJucePathModules.contains (m)) | |||
| userPathModules.addItem (index++, m, ! modules.isModuleEnabled (m)); | |||
| } | |||
| knownModules.addSubMenu ("Global user modules path", userPathModules); | |||
| index = 300; | |||
| for (auto m : getAvailableModulesInExporterPaths()) | |||
| { | |||
| if (! globalJucePathModules.contains (m) && ! globalUserPathModules.contains (m)) | |||
| exporterPathsModules.addItem (index++, m, ! modules.isModuleEnabled (m)); | |||
| } | |||
| knownModules.addSubMenu ("Exporter paths", exporterPathsModules); | |||
| PopupMenu menu; | |||
| menu.addSubMenu ("Add a module", knownModules); | |||
| menu.addSeparator(); | |||
| menu.addItem (1001, "Add a module from a specified folder..."); | |||
| @@ -396,16 +505,51 @@ public: | |||
| void handlePopupMenuResult (int resultCode) override | |||
| { | |||
| auto& modules = project.getModules(); | |||
| if (resultCode == 1001) | |||
| project.getModules().addModuleFromUserSelectedFile(); | |||
| { | |||
| modules.addModuleFromUserSelectedFile(); | |||
| } | |||
| else if (resultCode > 0) | |||
| project.getModules().addModuleInteractive (getAvailableModules() [resultCode - 1]); | |||
| { | |||
| if (resultCode < 200) | |||
| modules.addModuleInteractive (getAvailableModulesInGlobalJucePath() [resultCode - 100]); | |||
| else if (resultCode < 300) | |||
| modules.addModuleInteractive (getAvailableModulesInGlobalUserPath() [resultCode - 200]); | |||
| else if (resultCode < 400) | |||
| modules.addModuleInteractive (getAvailableModulesInExporterPaths() [resultCode - 300]); | |||
| } | |||
| } | |||
| StringArray getAvailableModulesInExporterPaths() | |||
| { | |||
| ModuleList list; | |||
| list.scanProjectExporterModulePaths (project); | |||
| return list.getIDs(); | |||
| } | |||
| StringArray getAvailableModulesInGlobalJucePath() | |||
| { | |||
| ModuleList list; | |||
| list.addAllModulesInFolder ({ getAppSettings().getStoredPath (Ids::defaultJuceModulePath).toString() }); | |||
| return list.getIDs(); | |||
| } | |||
| StringArray getAvailableModules() | |||
| StringArray getAvailableModulesInGlobalUserPath() | |||
| { | |||
| ModuleList list; | |||
| list.scanAllKnownFolders (project); | |||
| auto paths = StringArray::fromTokens (getAppSettings().getStoredPath (Ids::defaultUserModulePath).toString(), ";", {}); | |||
| for (auto p : paths) | |||
| { | |||
| auto f = File::createFileWithoutCheckingPath (p.trim()); | |||
| if (f.exists()) | |||
| list.addAllModulesInFolder (f); | |||
| } | |||
| return list.getIDs(); | |||
| } | |||
| @@ -26,8 +26,6 @@ | |||
| #include "../jucer_Headers.h" | |||
| #include "jucer_DependencyPathPropertyComponent.h" | |||
| #include "../Application/jucer_GlobalPreferences.h" | |||
| //============================================================================== | |||
| DependencyPathValueSource::DependencyPathValueSource (const Value& projectSettingsPath, | |||
| @@ -36,10 +34,11 @@ DependencyPathValueSource::DependencyPathValueSource (const Value& projectSettin | |||
| : projectSettingsValue (projectSettingsPath), | |||
| globalKey (globalSettingsKey), | |||
| os (osThisSettingAppliesTo), | |||
| globalSettingsValue (getAppSettings().getGlobalPath (globalKey, os)), | |||
| fallbackValue (getAppSettings().getFallbackPath (globalKey, os)) | |||
| globalSettingsValue (getAppSettings().getStoredPath (globalKey)), | |||
| fallbackValue (getAppSettings().getFallbackPathForOS (globalKey, os)) | |||
| { | |||
| globalSettingsValue.addListener (this); | |||
| fallbackValue.addListener (this); | |||
| } | |||
| bool DependencyPathValueSource::isValidPath (const File& relativeTo) const | |||
| @@ -135,3 +134,153 @@ void DependencyPathPropertyComponent::lookAndFeelChanged() | |||
| { | |||
| textWasEdited(); | |||
| } | |||
| //============================================================================== | |||
| DependencyFilePathPropertyComponent::DependencyFilePathPropertyComponent (Value& value, | |||
| const String& propertyDescription, | |||
| bool isDir, | |||
| const String& wc, | |||
| const File& rootToUseForRelativePaths) | |||
| try : TextPropertyComponent (propertyDescription, 1024, false), | |||
| pathRelativeTo (rootToUseForRelativePaths), | |||
| pathValue (value), | |||
| pathValueSource (dynamic_cast<DependencyPathValueSource&> (pathValue.getValueSource())), | |||
| browseButton ("..."), | |||
| isDirectory (isDir), | |||
| wildcards (wc) | |||
| { | |||
| auto initialValueIsEmpty = ! pathValueSource.isUsingProjectSettings(); | |||
| getValue().referTo (pathValue); | |||
| if (initialValueIsEmpty) | |||
| getValue().setValue (String()); | |||
| getValue().addListener (this); | |||
| if (auto* label = dynamic_cast<Label*> (getChildComponent (0))) | |||
| label->addListener (this); | |||
| else | |||
| jassertfalse; | |||
| setInterestedInFileDrag (false); | |||
| addAndMakeVisible (browseButton); | |||
| browseButton.addListener (this); | |||
| lookAndFeelChanged(); | |||
| } | |||
| catch (const std::bad_cast&) | |||
| { | |||
| // a DependencyPathPropertyComponent must be initialised with a Value | |||
| // that is referring to a DependencyPathValueSource! | |||
| jassertfalse; | |||
| throw; | |||
| } | |||
| void DependencyFilePathPropertyComponent::resized() | |||
| { | |||
| auto bounds = getLookAndFeel().getPropertyComponentContentPosition (*this); | |||
| browseButton.setBounds (bounds.removeFromRight (30)); | |||
| getChildComponent (0)->setBounds (bounds); | |||
| } | |||
| void DependencyFilePathPropertyComponent::paintOverChildren (Graphics& g) | |||
| { | |||
| if (highlightForDragAndDrop) | |||
| { | |||
| g.setColour (findColour (defaultHighlightColourId).withAlpha (0.5f)); | |||
| g.fillRect (getChildComponent (0)->getBounds()); | |||
| } | |||
| } | |||
| void DependencyFilePathPropertyComponent::filesDropped (const StringArray& files, int, int) | |||
| { | |||
| const File firstFile (files[0]); | |||
| if (isDirectory) | |||
| setTo (firstFile.isDirectory() ? firstFile | |||
| : firstFile.getParentDirectory()); | |||
| else | |||
| setTo (firstFile); | |||
| highlightForDragAndDrop = false; | |||
| } | |||
| void DependencyFilePathPropertyComponent::setTo (const File& f) | |||
| { | |||
| pathValue = (pathRelativeTo == File()) ? f.getFullPathName() | |||
| : f.getRelativePathFrom (pathRelativeTo); | |||
| textWasEdited(); | |||
| } | |||
| void DependencyFilePathPropertyComponent::enablementChanged() | |||
| { | |||
| getValue().referTo (isEnabled() ? pathValue | |||
| : pathValueSource.appliesToThisOS() ? pathValueSource.getGlobalSettingsValue() | |||
| : pathValueSource.getFallbackSettingsValue()); | |||
| textWasEdited(); | |||
| repaint(); | |||
| } | |||
| void DependencyFilePathPropertyComponent::textWasEdited() | |||
| { | |||
| setColour (textColourId, getTextColourToDisplay()); | |||
| TextPropertyComponent::textWasEdited(); | |||
| } | |||
| void DependencyFilePathPropertyComponent::valueChanged (Value& value) | |||
| { | |||
| if ((value.refersToSameSourceAs (pathValue) && pathValueSource.isUsingGlobalSettings()) | |||
| || value.refersToSameSourceAs (pathValueSource.getGlobalSettingsValue())) | |||
| textWasEdited(); | |||
| } | |||
| void DependencyFilePathPropertyComponent::editorShown (Label*, TextEditor& editor) | |||
| { | |||
| if (! pathValueSource.isUsingProjectSettings()) | |||
| editor.setText (String(), dontSendNotification); | |||
| } | |||
| void DependencyFilePathPropertyComponent::buttonClicked (Button*) | |||
| { | |||
| auto currentFile = pathRelativeTo.getChildFile (pathValue.toString()); | |||
| if (isDirectory) | |||
| { | |||
| FileChooser chooser ("Select directory", currentFile); | |||
| if (chooser.browseForDirectory()) | |||
| setTo (chooser.getResult()); | |||
| } | |||
| else | |||
| { | |||
| FileChooser chooser ("Select file", currentFile, wildcards); | |||
| if (chooser.browseForFileToOpen()) | |||
| setTo (chooser.getResult()); | |||
| } | |||
| } | |||
| Colour DependencyFilePathPropertyComponent::getTextColourToDisplay() const | |||
| { | |||
| auto alpha = 1.0f; | |||
| auto key = pathValueSource.getKey(); | |||
| const auto& globalSettingsValue = pathValueSource.getGlobalSettingsValue(); | |||
| if (! pathValueSource.isUsingProjectSettings() && isEnabled()) | |||
| alpha = 0.5f; | |||
| if ((key == Ids::defaultUserModulePath && getValue().toString().contains (";")) || ! pathValueSource.appliesToThisOS()) | |||
| return findColour (widgetTextColourId).withMultipliedAlpha (alpha); | |||
| auto usingGlobalPath = (getValue().refersToSameSourceAs (globalSettingsValue)); | |||
| auto isValidPath = getAppSettings().isGlobalPathValid (pathRelativeTo, key, | |||
| (usingGlobalPath ? globalSettingsValue : pathValue).toString()); | |||
| return isValidPath ? findColour (widgetTextColourId).withMultipliedAlpha (alpha) | |||
| : Colours::red.withMultipliedAlpha (alpha); | |||
| } | |||
| @@ -52,7 +52,7 @@ public: | |||
| if (isUsingGlobalSettings()) | |||
| return globalSettingsValue.getValue(); | |||
| return fallbackValue; | |||
| return fallbackValue.getValue(); | |||
| } | |||
| void setValue (const var& newValue) override | |||
| @@ -75,7 +75,7 @@ public: | |||
| bool isUsingFallbackValue() const | |||
| { | |||
| return ! projectSettingsValueIsValid() && !globalSettingsValueIsValid(); | |||
| return ! projectSettingsValueIsValid() && ! globalSettingsValueIsValid(); | |||
| } | |||
| bool appliesToThisOS() const | |||
| @@ -87,10 +87,16 @@ public: | |||
| bool isValidPath() const; | |||
| Identifier getKey() { return globalKey; } | |||
| Value getGlobalSettingsValue() { return globalSettingsValue; } | |||
| Value getFallbackSettingsValue() { return fallbackValue; } | |||
| private: | |||
| void valueChanged (Value& value) override | |||
| { | |||
| if ((value.refersToSameSourceAs (globalSettingsValue) && isUsingGlobalSettings())) | |||
| if ((value.refersToSameSourceAs (globalSettingsValue) && isUsingGlobalSettings()) | |||
| || (value.refersToSameSourceAs (fallbackValue) && isUsingFallbackValue())) | |||
| { | |||
| sendChangeMessage (true); | |||
| setValue (String()); // make sure that the project-specific value is still blank | |||
| @@ -136,7 +142,7 @@ private: | |||
| /** the dependency path fallback setting. used instead of the global setting | |||
| whenever the latter doesn't apply, e.g. the setting is for another | |||
| OS than the ome this machine is running. */ | |||
| String fallbackValue; | |||
| Value fallbackValue; | |||
| }; | |||
| @@ -181,3 +187,61 @@ private: | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DependencyPathPropertyComponent) | |||
| }; | |||
| //============================================================================== | |||
| class DependencyFilePathPropertyComponent : public TextPropertyComponent, | |||
| public FileDragAndDropTarget, | |||
| private Value::Listener, | |||
| private Label::Listener, | |||
| private Button::Listener | |||
| { | |||
| public: | |||
| DependencyFilePathPropertyComponent (Value& value, | |||
| const String& propertyDescription, | |||
| bool isDirectory, | |||
| const String& wildcards = "*", | |||
| const File& rootToUseForRelativePaths = File()); | |||
| void resized() override; | |||
| void paintOverChildren (Graphics& g) override; | |||
| bool isInterestedInFileDrag (const StringArray&) override { return isEnabled(); } | |||
| void fileDragEnter (const StringArray&, int, int) override { highlightForDragAndDrop = true; repaint(); } | |||
| void fileDragExit (const StringArray&) override { highlightForDragAndDrop = false; repaint(); } | |||
| void filesDropped (const StringArray&, int, int) override; | |||
| void setTo (const File& f); | |||
| void enablementChanged() override; | |||
| private: | |||
| void textWasEdited() override; | |||
| void valueChanged (Value&) override; | |||
| void labelTextChanged (Label*) override {} | |||
| void editorHidden (Label*, TextEditor&) override {} | |||
| void editorShown (Label*, TextEditor&) override; | |||
| void buttonClicked (Button*) override; | |||
| void lookAndFeelChanged() override | |||
| { | |||
| browseButton.setColour (TextButton::buttonColourId, | |||
| findColour (secondaryButtonBackgroundColourId)); | |||
| textWasEdited(); | |||
| } | |||
| Colour getTextColourToDisplay() const; | |||
| //========================================================================== | |||
| File pathRelativeTo; | |||
| Value pathValue; | |||
| DependencyPathValueSource& pathValueSource; | |||
| TextButton browseButton; | |||
| bool isDirectory, highlightForDragAndDrop = false; | |||
| String wildcards; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DependencyFilePathPropertyComponent) | |||
| }; | |||
| @@ -209,15 +209,23 @@ Result ModuleList::addAllModulesInSubfoldersRecursively (const File& path, int d | |||
| return Result::ok(); | |||
| } | |||
| static Array<File> getAllPossibleModulePaths (Project& project) | |||
| static Array<File> getAllPossibleModulePathsFromExporters (Project& project) | |||
| { | |||
| StringArray paths; | |||
| for (Project::ExporterIterator exporter (project); exporter.next();) | |||
| { | |||
| for (int i = 0; i < project.getModules().getNumModules(); ++i) | |||
| auto& modules = project.getModules(); | |||
| auto n = modules.getNumModules(); | |||
| for (int i = 0; i < n; ++i) | |||
| { | |||
| const String path (exporter->getPathForModuleString (project.getModules().getModuleID (i))); | |||
| auto id = modules.getModuleID (i); | |||
| if (modules.shouldUseGlobalPath (id).getValue()) | |||
| continue; | |||
| const auto path = exporter->getPathForModuleString (id); | |||
| if (path.isNotEmpty()) | |||
| paths.addIfNotAlreadyThere (path); | |||
| @@ -237,7 +245,7 @@ static Array<File> getAllPossibleModulePaths (Project& project) | |||
| if (f.isDirectory()) | |||
| { | |||
| files.add (f); | |||
| files.addIfNotAlreadyThere (f); | |||
| if (f.getChildFile ("modules").isDirectory()) | |||
| files.addIfNotAlreadyThere (f.getChildFile ("modules")); | |||
| @@ -247,12 +255,12 @@ static Array<File> getAllPossibleModulePaths (Project& project) | |||
| return files; | |||
| } | |||
| Result ModuleList::scanAllKnownFolders (Project& project) | |||
| Result ModuleList::scanProjectExporterModulePaths (Project& project) | |||
| { | |||
| modules.clear(); | |||
| Result result (Result::ok()); | |||
| for (auto& m : getAllPossibleModulePaths (project)) | |||
| for (auto& m : getAllPossibleModulePathsFromExporters (project)) | |||
| { | |||
| result = addAllModulesInFolder (m); | |||
| @@ -264,6 +272,36 @@ Result ModuleList::scanAllKnownFolders (Project& project) | |||
| return result; | |||
| } | |||
| void ModuleList::scanGlobalJuceModulePath() | |||
| { | |||
| modules.clear(); | |||
| auto& settings = getAppSettings(); | |||
| auto path = settings.getStoredPath (Ids::defaultJuceModulePath).toString(); | |||
| if (path.isNotEmpty()) | |||
| addAllModulesInFolder ({ path }); | |||
| sort(); | |||
| } | |||
| void ModuleList::scanGlobalUserModulePath() | |||
| { | |||
| modules.clear(); | |||
| auto paths = StringArray::fromTokens (getAppSettings().getStoredPath (Ids::defaultUserModulePath).toString(), ";", {}); | |||
| for (auto p : paths) | |||
| { | |||
| auto f = File::createFileWithoutCheckingPath (p.trim()); | |||
| if (f.exists()) | |||
| addAllModulesInFolder (f); | |||
| } | |||
| sort(); | |||
| } | |||
| //============================================================================== | |||
| LibraryModule::LibraryModule (const ModuleDescription& d) | |||
| : moduleInfo (d) | |||
| @@ -342,14 +380,16 @@ void LibraryModule::addSettingsForModuleToExporter (ProjectExporter& exporter, P | |||
| { | |||
| Array<File> compiled; | |||
| auto& modules = project.getModules(); | |||
| auto id = getID(); | |||
| const File localModuleFolder = project.getModules().shouldCopyModuleFilesLocally (getID()).getValue() | |||
| ? project.getLocalModuleFolder (getID()) | |||
| const File localModuleFolder = modules.shouldCopyModuleFilesLocally (id).getValue() | |||
| ? project.getLocalModuleFolder (id) | |||
| : moduleInfo.getFolder(); | |||
| findAndAddCompiledUnits (exporter, &projectSaver, compiled); | |||
| if (project.getModules().shouldShowAllModuleFilesInProject (getID()).getValue()) | |||
| if (modules.shouldShowAllModuleFilesInProject (id).getValue()) | |||
| addBrowseableCode (exporter, compiled, localModuleFolder); | |||
| } | |||
| @@ -606,35 +646,33 @@ bool EnabledModuleList::isAudioPluginModuleMissing() const | |||
| && ! isModuleEnabled ("juce_audio_plugin_client"); | |||
| } | |||
| Value EnabledModuleList::shouldUseGlobalPath (const String& moduleID) const | |||
| { | |||
| return state.getChildWithProperty (Ids::ID, moduleID) | |||
| .getPropertyAsValue (Ids::useGlobalPath, getUndoManager()); | |||
| } | |||
| Value EnabledModuleList::shouldShowAllModuleFilesInProject (const String& moduleID) | |||
| { | |||
| return state.getChildWithProperty (Ids::ID, moduleID) | |||
| .getPropertyAsValue (Ids::showAllCode, getUndoManager()); | |||
| } | |||
| File EnabledModuleList::findLocalModuleFolder (const String& moduleID, bool useExportersForOtherOSes) | |||
| File EnabledModuleList::getModuleFolderFromPathIfItExists (const String& path, const String& moduleID, const Project& project) | |||
| { | |||
| for (Project::ExporterIterator exporter (project); exporter.next();) | |||
| if (path.isNotEmpty()) | |||
| { | |||
| if (useExportersForOtherOSes || exporter->mayCompileOnCurrentOS()) | |||
| { | |||
| auto path = exporter->getPathForModuleString (moduleID); | |||
| auto moduleFolder = project.resolveFilename (path); | |||
| if (path.isNotEmpty()) | |||
| { | |||
| auto moduleFolder = project.resolveFilename (path); | |||
| if (moduleFolder.exists()) | |||
| { | |||
| if (ModuleDescription (moduleFolder).isValid()) | |||
| return moduleFolder; | |||
| if (moduleFolder.exists()) | |||
| { | |||
| if (ModuleDescription (moduleFolder).isValid()) | |||
| return moduleFolder; | |||
| auto f = moduleFolder.getChildFile (moduleID); | |||
| auto f = moduleFolder.getChildFile (moduleID); | |||
| if (ModuleDescription (f).isValid()) | |||
| return f; | |||
| } | |||
| } | |||
| if (ModuleDescription (f).isValid()) | |||
| return f; | |||
| } | |||
| } | |||
| @@ -643,12 +681,23 @@ File EnabledModuleList::findLocalModuleFolder (const String& moduleID, bool useE | |||
| File EnabledModuleList::getModuleFolder (const String& moduleID) | |||
| { | |||
| File f = findLocalModuleFolder (moduleID, false); | |||
| if (shouldUseGlobalPath (moduleID).getValue()) | |||
| { | |||
| if (isJuceModule (moduleID)) | |||
| return getModuleFolderFromPathIfItExists (getAppSettings().getStoredPath (Ids::defaultJuceModulePath).toString(), moduleID, project); | |||
| return findUserModuleFolder (moduleID, getAppSettings().getStoredPath (Ids::defaultUserModulePath).toString(), project); | |||
| } | |||
| if (f == File()) | |||
| f = findLocalModuleFolder (moduleID, true); | |||
| auto paths = getAllPossibleModulePathsFromExporters (project); | |||
| for (auto p : paths) | |||
| { | |||
| auto f = getModuleFolderFromPathIfItExists (p.getFullPathName(), moduleID, project); | |||
| if (f != File()) | |||
| return f; | |||
| } | |||
| return f; | |||
| return {}; | |||
| } | |||
| struct ModuleTreeSorter | |||
| @@ -671,7 +720,7 @@ Value EnabledModuleList::shouldCopyModuleFilesLocally (const String& moduleID) c | |||
| .getPropertyAsValue (Ids::useLocalCopy, getUndoManager()); | |||
| } | |||
| void EnabledModuleList::addModule (const File& moduleFolder, bool copyLocally) | |||
| void EnabledModuleList::addModule (const File& moduleFolder, bool copyLocally, bool useGlobalPath) | |||
| { | |||
| ModuleDescription info (moduleFolder); | |||
| @@ -689,6 +738,7 @@ void EnabledModuleList::addModule (const File& moduleFolder, bool copyLocally) | |||
| shouldShowAllModuleFilesInProject (moduleID) = true; | |||
| shouldCopyModuleFilesLocally (moduleID) = copyLocally; | |||
| shouldUseGlobalPath (moduleID) = useGlobalPath; | |||
| RelativePath path (moduleFolder.getParentDirectory(), | |||
| project.getProjectFolder(), RelativePath::projectFolder); | |||
| @@ -720,7 +770,7 @@ StringArray EnabledModuleList::getAllModules() const | |||
| StringArray moduleIDs; | |||
| for (int i = 0; i < getNumModules(); ++i) | |||
| moduleIDs.add (getModuleID(i)); | |||
| moduleIDs.add (getModuleID (i)); | |||
| return moduleIDs; | |||
| } | |||
| @@ -751,11 +801,26 @@ StringArray EnabledModuleList::getExtraDependenciesNeeded (const String& moduleI | |||
| return extraDepsNeeded; | |||
| } | |||
| bool EnabledModuleList::areMostModulesUsingGlobalPath() const | |||
| { | |||
| auto numYes = 0, numNo = 0; | |||
| for (auto i = getNumModules(); --i >= 0;) | |||
| { | |||
| if (shouldUseGlobalPath (getModuleID (i)).getValue()) | |||
| ++numYes; | |||
| else | |||
| ++numNo; | |||
| } | |||
| return numYes > numNo; | |||
| } | |||
| bool EnabledModuleList::areMostModulesCopiedLocally() const | |||
| { | |||
| int numYes = 0, numNo = 0; | |||
| auto numYes = 0, numNo = 0; | |||
| for (int i = getNumModules(); --i >= 0;) | |||
| for (auto i = getNumModules(); --i >= 0;) | |||
| { | |||
| if (shouldCopyModuleFilesLocally (getModuleID (i)).getValue()) | |||
| ++numYes; | |||
| @@ -772,10 +837,26 @@ void EnabledModuleList::setLocalCopyModeForAllModules (bool copyLocally) | |||
| shouldCopyModuleFilesLocally (project.getModules().getModuleID (i)) = copyLocally; | |||
| } | |||
| File EnabledModuleList::findGlobalModulesFolder() | |||
| { | |||
| auto& settings = getAppSettings(); | |||
| auto path = settings.getStoredPath (Ids::defaultJuceModulePath).toString(); | |||
| if (settings.isGlobalPathValid (File(), Ids::defaultJuceModulePath, path)) | |||
| return { path }; | |||
| return {}; | |||
| } | |||
| File EnabledModuleList::findDefaultModulesFolder (Project& project) | |||
| { | |||
| auto globalPath = findGlobalModulesFolder(); | |||
| if (globalPath != File()) | |||
| return globalPath; | |||
| ModuleList available; | |||
| available.scanAllKnownFolders (project); | |||
| available.scanProjectExporterModulePaths (project); | |||
| for (int i = available.modules.size(); --i >= 0;) | |||
| { | |||
| @@ -788,6 +869,52 @@ File EnabledModuleList::findDefaultModulesFolder (Project& project) | |||
| return File::getCurrentWorkingDirectory(); | |||
| } | |||
| File EnabledModuleList::findUserModuleFolder (const String& moduleID, const String& possiblePaths, const Project& project) | |||
| { | |||
| auto paths = StringArray::fromTokens (possiblePaths, ";", {}); | |||
| for (auto p : paths) | |||
| { | |||
| auto f = File::createFileWithoutCheckingPath (p.trim()); | |||
| if (f.exists()) | |||
| { | |||
| auto moduleFolder = getModuleFolderFromPathIfItExists (f.getFullPathName(), moduleID, project); | |||
| if (moduleFolder != File()) | |||
| return moduleFolder; | |||
| } | |||
| } | |||
| return {}; | |||
| } | |||
| bool EnabledModuleList::isJuceModule (const String& moduleID) | |||
| { | |||
| static StringArray juceModuleIds = | |||
| { | |||
| "juce_audio_basics", | |||
| "juce_audio_devices", | |||
| "juce_audio_formats", | |||
| "juce_audio_plugin_client", | |||
| "juce_audio_processors", | |||
| "juce_audio_utils", | |||
| "juce_blocks_basics", | |||
| "juce_box2d", | |||
| "juce_core", | |||
| "juce_cryptography", | |||
| "juce_data_structures", | |||
| "juce_events", | |||
| "juce_graphics", | |||
| "juce_gui_basics", | |||
| "juce_gui_extra", | |||
| "juce_opengl", | |||
| "juce_osc", | |||
| "juce_product_unlocking", | |||
| "juce_video" | |||
| }; | |||
| return juceModuleIds.contains (moduleID); | |||
| } | |||
| void EnabledModuleList::addModuleFromUserSelectedFile() | |||
| { | |||
| static File lastLocation (findDefaultModulesFolder (project)); | |||
| @@ -804,10 +931,24 @@ void EnabledModuleList::addModuleFromUserSelectedFile() | |||
| void EnabledModuleList::addModuleInteractive (const String& moduleID) | |||
| { | |||
| ModuleList list; | |||
| list.scanAllKnownFolders (project); | |||
| list.scanGlobalJuceModulePath(); | |||
| if (auto* info = list.getModuleWithID (moduleID)) | |||
| { | |||
| addModule (info->moduleFolder, areMostModulesCopiedLocally(), areMostModulesUsingGlobalPath()); | |||
| return; | |||
| } | |||
| list.scanGlobalUserModulePath(); | |||
| if (auto* info = list.getModuleWithID (moduleID)) | |||
| { | |||
| addModule (info->moduleFolder, areMostModulesCopiedLocally(), areMostModulesUsingGlobalPath()); | |||
| return; | |||
| } | |||
| list.scanProjectExporterModulePaths (project); | |||
| if (auto* info = list.getModuleWithID (moduleID)) | |||
| addModule (info->moduleFolder, areMostModulesCopiedLocally()); | |||
| addModule (info->moduleFolder, areMostModulesCopiedLocally(), false); | |||
| else | |||
| addModuleFromUserSelectedFile(); | |||
| } | |||
| @@ -830,7 +971,7 @@ void EnabledModuleList::addModuleOfferingToCopy (const File& f) | |||
| return; | |||
| } | |||
| addModule (m.moduleFolder, areMostModulesCopiedLocally()); | |||
| addModule (m.moduleFolder, areMostModulesCopiedLocally(), areMostModulesUsingGlobalPath()); | |||
| } | |||
| bool isJuceFolder (const File& f) | |||
| @@ -31,7 +31,6 @@ class ProjectExporter; | |||
| class ProjectSaver; | |||
| //============================================================================== | |||
| File findDefaultModulesFolder (bool mustContainJuceCoreModule = true); | |||
| bool isJuceModulesFolder (const File&); | |||
| bool isJuceFolder (const File&); | |||
| @@ -79,7 +78,9 @@ struct ModuleList | |||
| Result addAllModulesInFolder (const File&); | |||
| Result addAllModulesInSubfoldersRecursively (const File&, int depth); | |||
| Result scanAllKnownFolders (Project&); | |||
| Result scanProjectExporterModulePaths (Project&); | |||
| void scanGlobalJuceModulePath(); | |||
| void scanGlobalUserModulePath(); | |||
| OwnedArray<ModuleDescription> modules; | |||
| }; | |||
| @@ -135,17 +136,24 @@ class EnabledModuleList | |||
| public: | |||
| EnabledModuleList (Project&, const ValueTree&); | |||
| static File findGlobalModulesFolder(); | |||
| static File findDefaultModulesFolder (Project&); | |||
| static File findUserModuleFolder (const String& moduleID, const String& possiblePaths, const Project&); | |||
| static bool isJuceModule (const String& moduleID); | |||
| bool isModuleEnabled (const String& moduleID) const; | |||
| Value shouldUseGlobalPath (const String& moduleID) const; | |||
| Value shouldShowAllModuleFilesInProject (const String& moduleID); | |||
| Value shouldCopyModuleFilesLocally (const String& moduleID) const; | |||
| void removeModule (String moduleID); | |||
| bool isAudioPluginModuleMissing() const; | |||
| ModuleDescription getModuleInfo (const String& moduleID); | |||
| File getModuleFolder (const String& moduleID); | |||
| void addModule (const File& moduleManifestFile, bool copyLocally); | |||
| void addModule (const File& moduleManifestFile, bool copyLocally, bool useGlobalPath); | |||
| void addModuleInteractive (const String& moduleID); | |||
| void addModuleFromUserSelectedFile(); | |||
| void addModuleOfferingToCopy (const File&); | |||
| @@ -157,11 +165,12 @@ public: | |||
| int getNumModules() const { return state.getNumChildren(); } | |||
| String getModuleID (int index) const { return state.getChild (index) [Ids::ID].toString(); } | |||
| bool areMostModulesUsingGlobalPath() const; | |||
| bool areMostModulesCopiedLocally() const; | |||
| void setLocalCopyModeForAllModules (bool copyLocally); | |||
| void sortAlphabetically(); | |||
| static File findDefaultModulesFolder (Project&); | |||
| void sortAlphabetically(); | |||
| Project& project; | |||
| ValueTree state; | |||
| @@ -169,7 +178,7 @@ public: | |||
| private: | |||
| UndoManager* getUndoManager() const { return project.getUndoManagerFor (state); } | |||
| File findLocalModuleFolder (const String& moduleID, bool useExportersForOtherOSes); | |||
| static File getModuleFolderFromPathIfItExists (const String& path, const String& moduleID, const Project&); | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (EnabledModuleList) | |||
| }; | |||
| @@ -35,7 +35,8 @@ public: | |||
| modulesValueTree (p.getModules().state), | |||
| header ("Modules", Icon (getIcons().modules, Colours::transparentBlack)), | |||
| setCopyModeButton ("Set copy-mode for all modules..."), | |||
| copyPathButton ("Set paths for all modules...") | |||
| copyPathButton ("Set paths for all modules..."), | |||
| globalPathsButton ("Enable/disable global path for all modules...") | |||
| { | |||
| listHeader = new ListBoxHeader ( { "Module", "Version", "Make Local Copy", "Paths" }, | |||
| { 0.25f, 0.2f, 0.2f, 0.35f } ); | |||
| @@ -51,10 +52,12 @@ public: | |||
| addAndMakeVisible (setCopyModeButton); | |||
| addAndMakeVisible (copyPathButton); | |||
| addAndMakeVisible (globalPathsButton); | |||
| setCopyModeButton.addListener (this); | |||
| setCopyModeButton.setTriggeredOnMouseDown (true); | |||
| copyPathButton.addListener (this); | |||
| copyPathButton.setTriggeredOnMouseDown (true); | |||
| globalPathsButton.addListener (this); | |||
| modulesValueTree.addListener (this); | |||
| lookAndFeelChanged(); | |||
| @@ -85,13 +88,15 @@ public: | |||
| setCopyModeButton.setBounds (buttonRow.removeFromLeft (jmin (200, bounds.getWidth() / 3))); | |||
| buttonRow.removeFromLeft (8); | |||
| copyPathButton.setBounds (buttonRow.removeFromLeft (jmin (200, bounds.getWidth() / 3))); | |||
| buttonRow.removeFromLeft (8); | |||
| globalPathsButton.setBounds (buttonRow.removeFromLeft (jmin (200, bounds.getWidth() / 3))); | |||
| } | |||
| } | |||
| void parentSizeChanged() override | |||
| { | |||
| const auto width = jmax (550, getParentWidth()); | |||
| auto y = list.getRowPosition (getNumRows() - 1, true).getBottom() + 100; | |||
| auto y = list.getRowPosition (getNumRows() - 1, true).getBottom() + 200; | |||
| y = jmax (getParentHeight(), y); | |||
| @@ -135,12 +140,21 @@ public: | |||
| g.drawFittedText (copyLocally, bounds.removeFromLeft (roundToInt (listHeader->getProportionAtIndex (2) * width)), Justification::centredLeft, 1); | |||
| //====================================================================== | |||
| StringArray paths; | |||
| String pathText; | |||
| for (Project::ExporterIterator exporter (project); exporter.next();) | |||
| paths.addIfNotAlreadyThere (exporter->getPathForModuleString (moduleID).trim()); | |||
| if (project.getModules().shouldUseGlobalPath (moduleID).getValue()) | |||
| { | |||
| pathText = "Global"; | |||
| } | |||
| else | |||
| { | |||
| StringArray paths; | |||
| const auto pathText = paths.joinIntoString (", "); | |||
| for (Project::ExporterIterator exporter (project); exporter.next();) | |||
| paths.addIfNotAlreadyThere (exporter->getPathForModuleString (moduleID).trim()); | |||
| pathText = paths.joinIntoString (", "); | |||
| } | |||
| g.drawFittedText (pathText, bounds.removeFromLeft (roundToInt (listHeader->getProportionAtIndex (3) * width)), Justification::centredLeft, 1); | |||
| } | |||
| @@ -163,12 +177,14 @@ public: | |||
| { | |||
| if (b == &setCopyModeButton) showCopyModeMenu(); | |||
| if (b == ©PathButton) showSetPathsMenu(); | |||
| if (b == &globalPathsButton) showGlobalPathsMenu(); | |||
| } | |||
| void lookAndFeelChanged() override | |||
| { | |||
| setCopyModeButton.setColour (TextButton::buttonColourId, findColour (secondaryButtonBackgroundColourId)); | |||
| copyPathButton.setColour (TextButton::buttonColourId, findColour (defaultButtonBackgroundColourId)); | |||
| globalPathsButton.setColour (TextButton::buttonColourId, findColour (defaultButtonBackgroundColourId)); | |||
| } | |||
| private: | |||
| @@ -185,7 +201,7 @@ private: | |||
| ContentViewHeader header; | |||
| ListBox list; | |||
| ListBoxHeader* listHeader; | |||
| TextButton setCopyModeButton, copyPathButton; | |||
| TextButton setCopyModeButton, copyPathButton, globalPathsButton; | |||
| std::map<String, var> modulePathClipboard; | |||
| void valueTreePropertyChanged (ValueTree&, const Identifier&) override { itemChanged(); } | |||
| @@ -207,12 +223,32 @@ private: | |||
| m.addItem (1, "Set all modules to copy locally"); | |||
| m.addItem (2, "Set all modules to not copy locally"); | |||
| int res = m.showAt (&setCopyModeButton); | |||
| auto res = m.showAt (&setCopyModeButton); | |||
| if (res != 0) | |||
| project.getModules().setLocalCopyModeForAllModules (res == 1); | |||
| } | |||
| void showGlobalPathsMenu() | |||
| { | |||
| PopupMenu m; | |||
| m.addItem (1, "Set all modules to use global paths"); | |||
| m.addItem (2, "Set all modules to not use global paths"); | |||
| auto res = m.showAt (&globalPathsButton); | |||
| if (res != 0) | |||
| { | |||
| auto enableGlobalPaths = (res == 1); | |||
| auto& modules = project.getModules(); | |||
| auto moduleIDs = modules.getAllModules(); | |||
| for (auto id : moduleIDs) | |||
| modules.shouldUseGlobalPath (id).setValue (enableGlobalPaths); | |||
| } | |||
| } | |||
| void showSetPathsMenu() | |||
| { | |||
| enum | |||
| @@ -307,20 +307,28 @@ static bool isAnyModuleNewerThanProjucer (const OwnedArray<ModuleDescription>& m | |||
| void Project::warnAboutOldProjucerVersion() | |||
| { | |||
| ModuleList available; | |||
| available.scanAllKnownFolders (*this); | |||
| if (isAnyModuleNewerThanProjucer (available.modules)) | |||
| { | |||
| if (ProjucerApplication::getApp().isRunningCommandLine) | |||
| std::cout << "WARNING! This version of the Projucer is out-of-date!" << std::endl; | |||
| else | |||
| AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
| "Projucer", | |||
| "This version of the Projucer is out-of-date!" | |||
| "\n\n" | |||
| "Always make sure that you're running the very latest version, " | |||
| "preferably compiled directly from the JUCE repository that you're working with!"); | |||
| } | |||
| available.scanGlobalJuceModulePath(); | |||
| if (! isAnyModuleNewerThanProjucer (available.modules)) | |||
| available.scanGlobalUserModulePath(); | |||
| if (! isAnyModuleNewerThanProjucer (available.modules)) | |||
| available.scanProjectExporterModulePaths (*this); | |||
| if (! isAnyModuleNewerThanProjucer (available.modules)) | |||
| return; | |||
| // Projucer is out of date! | |||
| if (ProjucerApplication::getApp().isRunningCommandLine) | |||
| std::cout << "WARNING! This version of the Projucer is out-of-date!" << std::endl; | |||
| else | |||
| AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
| "Projucer", | |||
| "This version of the Projucer is out-of-date!" | |||
| "\n\n" | |||
| "Always make sure that you're running the very latest version, " | |||
| "preferably compiled directly from the JUCE repository that you're working with!"); | |||
| } | |||
| //============================================================================== | |||
| @@ -423,6 +431,11 @@ File Project::resolveFilename (String filename) const | |||
| filename = replacePreprocessorDefs (getPreprocessorDefs(), filename); | |||
| #if ! JUCE_WINDOWS | |||
| if (filename.startsWith ("~")) | |||
| return File::getSpecialLocation (File::userHomeDirectory).getChildFile (filename.trimCharactersAtStart ("~/")); | |||
| #endif | |||
| if (FileHelpers::isAbsolutePath (filename)) | |||
| return File::createFileWithoutCheckingPath (FileHelpers::currentOSStylePath (filename)); // (avoid assertions for windows-style paths) | |||
| @@ -32,6 +32,7 @@ | |||
| #include "../Wizards/jucer_NewFileWizard.h" | |||
| #include "jucer_GroupInformationComponent.h" | |||
| #include "jucer_ModulesPanel.h" | |||
| #include "jucer_DependencyPathPropertyComponent.h" | |||
| struct FileTreeItemTypes | |||
| @@ -0,0 +1,344 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2017 - ROLI Ltd. | |||
| JUCE is an open source library subject to commercial or open-source | |||
| licensing. | |||
| By using JUCE, you agree to the terms of both the JUCE 5 End-User License | |||
| Agreement and JUCE 5 Privacy Policy (both updated and effective as of the | |||
| 27th April 2017). | |||
| End User License Agreement: www.juce.com/juce-5-licence | |||
| Privacy Policy: www.juce.com/juce-5-privacy-policy | |||
| Or: You may also use this code under the terms of the GPL v3 (see | |||
| www.gnu.org/licenses). | |||
| JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||
| EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||
| DISCLAIMED. | |||
| ============================================================================== | |||
| */ | |||
| #pragma once | |||
| #include "../Utility/jucer_ColourPropertyComponent.h" | |||
| class EditorColourSchemeWindowComponent : public Component | |||
| { | |||
| public: | |||
| EditorColourSchemeWindowComponent() | |||
| { | |||
| if (getAppSettings().monospacedFontNames.size() == 0) | |||
| content = new AppearanceEditor::FontScanPanel(); | |||
| else | |||
| content = new AppearanceEditor::EditorPanel(); | |||
| changeContent (content); | |||
| } | |||
| void paint (Graphics& g) override | |||
| { | |||
| g.fillAll (findColour (backgroundColourId)); | |||
| } | |||
| void resized() override | |||
| { | |||
| content->setBounds (getLocalBounds()); | |||
| } | |||
| void changeContent (Component* newContent) | |||
| { | |||
| content = newContent; | |||
| addAndMakeVisible (content); | |||
| content->setBounds (getLocalBounds().reduced (10)); | |||
| } | |||
| private: | |||
| ScopedPointer<Component> content; | |||
| //============================================================================== | |||
| struct AppearanceEditor | |||
| { | |||
| struct FontScanPanel : public Component, | |||
| private Timer | |||
| { | |||
| FontScanPanel() | |||
| { | |||
| fontsToScan = Font::findAllTypefaceNames(); | |||
| startTimer (1); | |||
| } | |||
| void paint (Graphics& g) override | |||
| { | |||
| g.fillAll (findColour (backgroundColourId)); | |||
| g.setFont (14.0f); | |||
| g.setColour (findColour (defaultTextColourId)); | |||
| g.drawFittedText ("Scanning for fonts..", getLocalBounds(), Justification::centred, 2); | |||
| const auto size = 30; | |||
| getLookAndFeel().drawSpinningWaitAnimation (g, Colours::white, (getWidth() - size) / 2, getHeight() / 2 - 50, size, size); | |||
| } | |||
| void timerCallback() override | |||
| { | |||
| repaint(); | |||
| if (fontsToScan.size() == 0) | |||
| { | |||
| getAppSettings().monospacedFontNames = fontsFound; | |||
| if (auto* owner = findParentComponentOfClass<EditorColourSchemeWindowComponent>()) | |||
| owner->changeContent (new EditorPanel()); | |||
| } | |||
| else | |||
| { | |||
| if (isMonospacedTypeface (fontsToScan[0])) | |||
| fontsFound.add (fontsToScan[0]); | |||
| fontsToScan.remove (0); | |||
| } | |||
| } | |||
| // A rather hacky trick to select only the fixed-pitch fonts.. | |||
| // This is unfortunately a bit slow, but will work on all platforms. | |||
| static bool isMonospacedTypeface (const String& name) | |||
| { | |||
| const Font font (name, 20.0f, Font::plain); | |||
| const auto width = font.getStringWidth ("...."); | |||
| return width == font.getStringWidth ("WWWW") | |||
| && width == font.getStringWidth ("0000") | |||
| && width == font.getStringWidth ("1111") | |||
| && width == font.getStringWidth ("iiii"); | |||
| } | |||
| StringArray fontsToScan, fontsFound; | |||
| }; | |||
| //============================================================================== | |||
| struct EditorPanel : public Component, | |||
| private ButtonListener | |||
| { | |||
| EditorPanel() | |||
| : loadButton ("Load Scheme..."), | |||
| saveButton ("Save Scheme...") | |||
| { | |||
| rebuildProperties(); | |||
| addAndMakeVisible (panel); | |||
| addAndMakeVisible (loadButton); | |||
| addAndMakeVisible (saveButton); | |||
| loadButton.addListener (this); | |||
| saveButton.addListener (this); | |||
| lookAndFeelChanged(); | |||
| saveSchemeState(); | |||
| } | |||
| ~EditorPanel() | |||
| { | |||
| if (hasSchemeBeenModifiedSinceSave()) | |||
| saveScheme (true); | |||
| } | |||
| void rebuildProperties() | |||
| { | |||
| auto& scheme = getAppSettings().appearance; | |||
| Array<PropertyComponent*> props; | |||
| auto fontValue = scheme.getCodeFontValue(); | |||
| props.add (FontNameValueSource::createProperty ("Code Editor Font", fontValue)); | |||
| props.add (FontSizeValueSource::createProperty ("Font Size", fontValue)); | |||
| const auto colourNames = scheme.getColourNames(); | |||
| for (int i = 0; i < colourNames.size(); ++i) | |||
| props.add (new ColourPropertyComponent (nullptr, colourNames[i], | |||
| scheme.getColourValue (colourNames[i]), | |||
| Colours::white, false)); | |||
| panel.clear(); | |||
| panel.addProperties (props); | |||
| } | |||
| void resized() override | |||
| { | |||
| auto r = getLocalBounds(); | |||
| panel.setBounds (r.removeFromTop (getHeight() - 28).reduced (10, 2)); | |||
| loadButton.setBounds (r.removeFromLeft (getWidth() / 2).reduced (10, 1)); | |||
| saveButton.setBounds (r.reduced (10, 1)); | |||
| } | |||
| private: | |||
| PropertyPanel panel; | |||
| TextButton loadButton, saveButton; | |||
| Font codeFont; | |||
| Array<var> colourValues; | |||
| void buttonClicked (Button* b) override | |||
| { | |||
| if (b == &loadButton) | |||
| loadScheme(); | |||
| else | |||
| saveScheme (false); | |||
| } | |||
| void saveScheme (bool isExit) | |||
| { | |||
| FileChooser fc ("Select a file in which to save this colour-scheme...", | |||
| getAppSettings().appearance.getSchemesFolder() | |||
| .getNonexistentChildFile ("Scheme", AppearanceSettings::getSchemeFileSuffix()), | |||
| AppearanceSettings::getSchemeFileWildCard()); | |||
| if (fc.browseForFileToSave (true)) | |||
| { | |||
| File file (fc.getResult().withFileExtension (AppearanceSettings::getSchemeFileSuffix())); | |||
| getAppSettings().appearance.writeToFile (file); | |||
| getAppSettings().appearance.refreshPresetSchemeList(); | |||
| saveSchemeState(); | |||
| ProjucerApplication::getApp().selectEditorColourSchemeWithName (file.getFileNameWithoutExtension()); | |||
| } | |||
| else if (isExit) | |||
| { | |||
| restorePreviousScheme(); | |||
| } | |||
| } | |||
| void loadScheme() | |||
| { | |||
| FileChooser fc ("Please select a colour-scheme file to load...", | |||
| getAppSettings().appearance.getSchemesFolder(), | |||
| AppearanceSettings::getSchemeFileWildCard()); | |||
| if (fc.browseForFileToOpen()) | |||
| { | |||
| if (getAppSettings().appearance.readFromFile (fc.getResult())) | |||
| { | |||
| rebuildProperties(); | |||
| saveSchemeState(); | |||
| } | |||
| } | |||
| } | |||
| void lookAndFeelChanged() override | |||
| { | |||
| loadButton.setColour (TextButton::buttonColourId, | |||
| findColour (secondaryButtonBackgroundColourId)); | |||
| } | |||
| void saveSchemeState() | |||
| { | |||
| auto& appearance = getAppSettings().appearance; | |||
| const auto colourNames = appearance.getColourNames(); | |||
| codeFont = appearance.getCodeFont(); | |||
| colourValues.clear(); | |||
| for (int i = 0; i < colourNames.size(); ++i) | |||
| colourValues.add (appearance.getColourValue (colourNames[i]).getValue()); | |||
| } | |||
| bool hasSchemeBeenModifiedSinceSave() | |||
| { | |||
| auto& appearance = getAppSettings().appearance; | |||
| const auto colourNames = appearance.getColourNames(); | |||
| if (codeFont != appearance.getCodeFont()) | |||
| return true; | |||
| for (int i = 0; i < colourNames.size(); ++i) | |||
| if (colourValues[i] != appearance.getColourValue (colourNames[i]).getValue()) | |||
| return true; | |||
| return false; | |||
| } | |||
| void restorePreviousScheme() | |||
| { | |||
| auto& appearance = getAppSettings().appearance; | |||
| const auto colourNames = appearance.getColourNames(); | |||
| appearance.getCodeFontValue().setValue (codeFont.toString()); | |||
| for (int i = 0; i < colourNames.size(); ++i) | |||
| appearance.getColourValue (colourNames[i]).setValue (colourValues[i]); | |||
| } | |||
| JUCE_DECLARE_NON_COPYABLE (EditorPanel) | |||
| }; | |||
| //============================================================================== | |||
| struct FontNameValueSource : public ValueSourceFilter | |||
| { | |||
| FontNameValueSource (const Value& source) : ValueSourceFilter (source) {} | |||
| var getValue() const override | |||
| { | |||
| return Font::fromString (sourceValue.toString()).getTypefaceName(); | |||
| } | |||
| void setValue (const var& newValue) override | |||
| { | |||
| auto font = Font::fromString (sourceValue.toString()); | |||
| font.setTypefaceName (newValue.toString().isEmpty() ? Font::getDefaultMonospacedFontName() | |||
| : newValue.toString()); | |||
| sourceValue = font.toString(); | |||
| } | |||
| static ChoicePropertyComponent* createProperty (const String& title, const Value& value) | |||
| { | |||
| auto fontNames = getAppSettings().monospacedFontNames; | |||
| Array<var> values; | |||
| values.add (Font::getDefaultMonospacedFontName()); | |||
| values.add (var()); | |||
| for (int i = 0; i < fontNames.size(); ++i) | |||
| values.add (fontNames[i]); | |||
| StringArray names; | |||
| names.add ("<Default Monospaced>"); | |||
| names.add (String()); | |||
| names.addArray (getAppSettings().monospacedFontNames); | |||
| return new ChoicePropertyComponent (Value (new FontNameValueSource (value)), | |||
| title, names, values); | |||
| } | |||
| }; | |||
| //============================================================================== | |||
| struct FontSizeValueSource : public ValueSourceFilter | |||
| { | |||
| FontSizeValueSource (const Value& source) : ValueSourceFilter (source) {} | |||
| var getValue() const override | |||
| { | |||
| return Font::fromString (sourceValue.toString()).getHeight(); | |||
| } | |||
| void setValue (const var& newValue) override | |||
| { | |||
| sourceValue = Font::fromString (sourceValue.toString()).withHeight (newValue).toString(); | |||
| } | |||
| static PropertyComponent* createProperty (const String& title, const Value& value) | |||
| { | |||
| return new SliderPropertyComponent (Value (new FontSizeValueSource (value)), | |||
| title, 5.0, 40.0, 0.1, 0.5); | |||
| } | |||
| }; | |||
| }; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (EditorColourSchemeWindowComponent) | |||
| }; | |||
| @@ -40,9 +40,10 @@ public: | |||
| const String& propertyDescription, | |||
| bool isDirectory, | |||
| const String& wildcards = "*", | |||
| const File& rootToUseForRelativePaths = File()) | |||
| const File& rootToUseForRelativePaths = File(), | |||
| const bool supportsMultiplePaths = false) | |||
| : PropertyComponent (propertyDescription), | |||
| innerComp (valueToControl, isDirectory, wildcards, rootToUseForRelativePaths) | |||
| innerComp (valueToControl, isDirectory, wildcards, rootToUseForRelativePaths, supportsMultiplePaths) | |||
| { | |||
| addAndMakeVisible (innerComp); | |||
| } | |||
| @@ -52,18 +53,21 @@ public: | |||
| private: | |||
| struct InnerComponent : public Component, | |||
| public FileDragAndDropTarget, | |||
| private Button::Listener | |||
| private Button::Listener, | |||
| private TextEditor::Listener | |||
| { | |||
| InnerComponent (Value v, bool isDir, const String& wc, const File& rt) | |||
| InnerComponent (Value v, bool isDir, const String& wc, const File& rt, const bool multiplePaths) | |||
| : value (v), | |||
| isDirectory (isDir), | |||
| highlightForDragAndDrop (false), | |||
| wildcards (wc), | |||
| root (rt), | |||
| button ("...") | |||
| button ("..."), | |||
| supportsMultiplePaths (multiplePaths) | |||
| { | |||
| addAndMakeVisible (textbox); | |||
| textbox.getTextValue().referTo (value); | |||
| textbox.addListener (this); | |||
| addAndMakeVisible (button); | |||
| button.addListener (this); | |||
| @@ -75,8 +79,8 @@ private: | |||
| { | |||
| if (highlightForDragAndDrop) | |||
| { | |||
| g.setColour (Colours::green.withAlpha (0.1f)); | |||
| g.fillRect (getLocalBounds()); | |||
| g.setColour (findColour (defaultHighlightColourId).withAlpha (0.5f)); | |||
| g.fillRect (textbox.getBounds()); | |||
| } | |||
| } | |||
| @@ -101,6 +105,9 @@ private: | |||
| : firstFile.getParentDirectory()); | |||
| else | |||
| setTo (firstFile); | |||
| highlightForDragAndDrop = false; | |||
| repaint(); | |||
| } | |||
| void buttonClicked (Button*) override | |||
| @@ -123,18 +130,74 @@ private: | |||
| } | |||
| } | |||
| void textEditorReturnKeyPressed (TextEditor& editor) override { updateEditorColour (editor); } | |||
| void textEditorFocusLost (TextEditor& editor) override { updateEditorColour (editor); } | |||
| void updateEditorColour (TextEditor& editor) | |||
| { | |||
| if (supportsMultiplePaths) | |||
| { | |||
| auto paths = StringArray::fromTokens (editor.getTextValue().toString(), ";", {}); | |||
| editor.clear(); | |||
| AttributedString str; | |||
| for (auto p : paths) | |||
| { | |||
| if (root.getChildFile (p.trim()).exists()) editor.setColour (TextEditor::textColourId, findColour (widgetTextColourId)); | |||
| else editor.setColour (TextEditor::textColourId, Colours::red); | |||
| editor.insertTextAtCaret (p); | |||
| if (paths.indexOf (p) < paths.size() - 1) | |||
| { | |||
| editor.setColour (TextEditor::textColourId, findColour (widgetTextColourId)); | |||
| editor.insertTextAtCaret (";"); | |||
| } | |||
| } | |||
| editor.setColour (TextEditor::textColourId, findColour (widgetTextColourId)); | |||
| } | |||
| else | |||
| { | |||
| auto pathToCheck = editor.getTextValue().toString(); | |||
| //android SDK/NDK paths | |||
| if (pathToCheck.contains ("${user.home}")) | |||
| pathToCheck = pathToCheck.replace ("${user.home}", File::getSpecialLocation (File::userHomeDirectory).getFullPathName()); | |||
| #if JUCE_WINDOWS | |||
| if (pathToCheck.startsWith ("~")) | |||
| pathToCheck = pathToCheck.replace ("~", File::getSpecialLocation (File::userHomeDirectory).getFullPathName()); | |||
| #endif | |||
| const auto currentFile = root.getChildFile (pathToCheck); | |||
| if (currentFile.exists()) | |||
| editor.applyColourToAllText (findColour (widgetTextColourId)); | |||
| else | |||
| editor.applyColourToAllText (Colours::red); | |||
| } | |||
| } | |||
| void setTo (const File& f) | |||
| { | |||
| value = (root == File()) ? f.getFullPathName() | |||
| : f.getRelativePathFrom (root); | |||
| auto pathName = (root == File()) ? f.getFullPathName() | |||
| : f.getRelativePathFrom (root); | |||
| if (supportsMultiplePaths && value.toString().isNotEmpty()) | |||
| value = value.toString().trimCharactersAtEnd (" ;") + "; " + pathName; | |||
| else | |||
| value = pathName; | |||
| updateEditorColour (textbox); | |||
| } | |||
| void lookAndFeelChanged() override | |||
| { | |||
| textbox.setColour (TextEditor::backgroundColourId, findColour (widgetBackgroundColourId)); | |||
| textbox.setColour (TextEditor::outlineColourId, Colours::transparentBlack); | |||
| textbox.setColour (TextEditor::textColourId, findColour (widgetTextColourId)); | |||
| textbox.applyFontToAllText (textbox.getFont()); | |||
| updateEditorColour (textbox); | |||
| button.setColour (TextButton::buttonColourId, findColour (secondaryButtonBackgroundColourId)); | |||
| button.setColour (TextButton::textColourOffId, Colours::white); | |||
| @@ -146,6 +209,7 @@ private: | |||
| File root; | |||
| TextEditor textbox; | |||
| TextButton button; | |||
| bool supportsMultiplePaths; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (InnerComponent) | |||
| }; | |||
| @@ -0,0 +1,200 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2017 - ROLI Ltd. | |||
| JUCE is an open source library subject to commercial or open-source | |||
| licensing. | |||
| By using JUCE, you agree to the terms of both the JUCE 5 End-User License | |||
| Agreement and JUCE 5 Privacy Policy (both updated and effective as of the | |||
| 27th April 2017). | |||
| End User License Agreement: www.juce.com/juce-5-licence | |||
| Privacy Policy: www.juce.com/juce-5-privacy-policy | |||
| Or: You may also use this code under the terms of the GPL v3 (see | |||
| www.gnu.org/licenses). | |||
| JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||
| EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||
| DISCLAIMED. | |||
| ============================================================================== | |||
| */ | |||
| #pragma once | |||
| class GlobalSearchPathsWindowComponent : public Component, | |||
| private ComboBox::Listener | |||
| { | |||
| public: | |||
| GlobalSearchPathsWindowComponent() | |||
| : modulesLabel ("modulesLabel", "Modules"), | |||
| sdksLabel ("sdksLabel", "SDKs") | |||
| { | |||
| addAndMakeVisible (modulesLabel); | |||
| addAndMakeVisible (sdksLabel); | |||
| modulesLabel.setFont (Font (18.0f, Font::FontStyleFlags::bold)); | |||
| sdksLabel.setFont (Font (18.0f, Font::FontStyleFlags::bold)); | |||
| modulesLabel.setJustificationType (Justification::centredLeft); | |||
| sdksLabel.setJustificationType (Justification::centredLeft); | |||
| addAndMakeVisible (info); | |||
| info.setInfoToDisplay ("Use this dropdown to set the global paths for different OSes. " | |||
| "\nN.B. These paths are stored locally and will only be used when " | |||
| "saving a project on this machine. Other machines will have their own " | |||
| "locally stored paths."); | |||
| addAndMakeVisible (osSelector); | |||
| osSelector.addItem ("OSX", 1); | |||
| osSelector.addItem ("Windows", 2); | |||
| osSelector.addItem ("Linux", 3); | |||
| osSelector.addListener (this); | |||
| auto os = TargetOS::getThisOS(); | |||
| if (os == TargetOS::osx) osSelector.setSelectedId (1); | |||
| else if (os == TargetOS::windows) osSelector.setSelectedId (2); | |||
| else if (os == TargetOS::linux) osSelector.setSelectedId (3); | |||
| updateFilePathPropertyComponents(); | |||
| } | |||
| void paint (Graphics& g) override | |||
| { | |||
| g.fillAll (findColour (backgroundColourId)); | |||
| } | |||
| void resized() override | |||
| { | |||
| auto b = getLocalBounds().reduced (10); | |||
| auto topSlice = b.removeFromTop (25); | |||
| osSelector.setSize (200, 25); | |||
| osSelector.setCentrePosition (topSlice.getCentre()); | |||
| info.setBounds (osSelector.getBounds().withWidth (osSelector.getHeight()).translated ((osSelector.getWidth() + 5), 0).reduced (2)); | |||
| modulesLabel.setBounds (b.removeFromTop (20)); | |||
| b.removeFromTop (20); | |||
| auto i = 0; | |||
| for (auto propertyComponent : pathPropertyComponents) | |||
| { | |||
| propertyComponent->setBounds (b.removeFromTop (propertyComponent->getPreferredHeight())); | |||
| b.removeFromTop (5); | |||
| if (i == 1) | |||
| { | |||
| b.removeFromTop (15); | |||
| sdksLabel.setBounds (b.removeFromTop (20)); | |||
| b.removeFromTop (20); | |||
| } | |||
| ++i; | |||
| } | |||
| } | |||
| private: | |||
| Label modulesLabel, sdksLabel; | |||
| OwnedArray<PropertyComponent> pathPropertyComponents; | |||
| ComboBox osSelector; | |||
| ConfigTreeItemTypes::InfoButton info; | |||
| void comboBoxChanged (ComboBox*) override | |||
| { | |||
| updateFilePathPropertyComponents(); | |||
| } | |||
| void updateFilePathPropertyComponents() | |||
| { | |||
| pathPropertyComponents.clear(); | |||
| auto thisOS = TargetOS::getThisOS(); | |||
| auto selectedOS = TargetOS::unknown; | |||
| switch (osSelector.getSelectedId()) | |||
| { | |||
| case 1: selectedOS = TargetOS::osx; break; | |||
| case 2: selectedOS = TargetOS::windows; break; | |||
| case 3: selectedOS = TargetOS::linux; break; | |||
| default: break; | |||
| } | |||
| auto& settings = getAppSettings(); | |||
| if (selectedOS == thisOS) | |||
| { | |||
| 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 (settings.getStoredPath (Ids::vst3Path), | |||
| "VST3 SDK", true))); | |||
| if (selectedOS == TargetOS::linux) | |||
| { | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (Value(), "RTAS SDK", true))); | |||
| pathPropertyComponents.getLast()->setEnabled (false); | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (Value(), "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))); | |||
| } | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (settings.getStoredPath (Ids::androidSDKPath), | |||
| "Android SDK", true))); | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (settings.getStoredPath (Ids::androidNDKPath), | |||
| "Android NDK", true))); | |||
| } | |||
| else | |||
| { | |||
| auto maxChars = 1024; | |||
| 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))); | |||
| addAndMakeVisible (pathPropertyComponents.add (new TextPropertyComponent (settings.getFallbackPathForOS (Ids::vst3Path, selectedOS), | |||
| "VST3 SDK", maxChars, false))); | |||
| 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))); | |||
| } | |||
| resized(); | |||
| } | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GlobalSearchPathsWindowComponent) | |||
| }; | |||
| @@ -59,6 +59,11 @@ namespace Ids | |||
| DECLARE_ID (intermediatesPath); | |||
| DECLARE_ID (modulePaths); | |||
| DECLARE_ID (searchpaths); | |||
| DECLARE_ID (osxFallback); | |||
| DECLARE_ID (windowsFallback); | |||
| DECLARE_ID (linuxFallback); | |||
| DECLARE_ID (defaultJuceModulePath); | |||
| DECLARE_ID (defaultUserModulePath); | |||
| DECLARE_ID (vst3Folder); | |||
| DECLARE_ID (rtasFolder); | |||
| DECLARE_ID (auFolder); | |||
| @@ -152,6 +157,7 @@ namespace Ids | |||
| DECLARE_ID (focusOrder); | |||
| DECLARE_ID (hidden); | |||
| DECLARE_ID (useStdCall); | |||
| DECLARE_ID (useGlobalPath); | |||
| DECLARE_ID (showAllCode); | |||
| DECLARE_ID (useLocalCopy); | |||
| DECLARE_ID (overwriteOnSave); | |||
| @@ -27,7 +27,6 @@ | |||
| #include "../jucer_Headers.h" | |||
| #include "jucer_StoredSettings.h" | |||
| #include "../Application/jucer_Application.h" | |||
| #include "../Application/jucer_GlobalPreferences.h" | |||
| //============================================================================== | |||
| StoredSettings& getAppSettings() | |||
| @@ -42,16 +41,20 @@ PropertiesFile& getGlobalProperties() | |||
| //============================================================================== | |||
| StoredSettings::StoredSettings() | |||
| : appearance (true), projectDefaults ("PROJECT_DEFAULT_SETTINGS") | |||
| : appearance (true), | |||
| projectDefaults ("PROJECT_DEFAULT_SETTINGS"), | |||
| fallbackPaths ("FALLBACK_PATHS") | |||
| { | |||
| updateOldProjectSettingsFiles(); | |||
| reload(); | |||
| projectDefaults.addListener (this); | |||
| fallbackPaths.addListener (this); | |||
| } | |||
| StoredSettings::~StoredSettings() | |||
| { | |||
| projectDefaults.removeListener (this); | |||
| fallbackPaths.removeListener (this); | |||
| flush(); | |||
| } | |||
| @@ -122,10 +125,13 @@ void StoredSettings::reload() | |||
| propertyFiles.add (createPropsFile ("Projucer", false)); | |||
| ScopedPointer<XmlElement> projectDefaultsXml (propertyFiles.getFirst()->getXmlValue ("PROJECT_DEFAULT_SETTINGS")); | |||
| if (projectDefaultsXml != nullptr) | |||
| projectDefaults = ValueTree::fromXml (*projectDefaultsXml); | |||
| ScopedPointer<XmlElement> fallbackPathsXml (propertyFiles.getFirst()->getXmlValue ("FALLBACK_PATHS")); | |||
| if (fallbackPathsXml != nullptr) | |||
| fallbackPaths = ValueTree::fromXml (*fallbackPathsXml); | |||
| // recent files... | |||
| recentFiles.restoreFromString (getGlobalProperties().getValue ("recentFiles")); | |||
| recentFiles.removeNonExistentFiles(); | |||
| @@ -228,61 +234,76 @@ void StoredSettings::ColourSelectorWithSwatches::setSwatchColour (int index, con | |||
| } | |||
| //============================================================================== | |||
| static bool doesSDKPathContainFile (const File& relativeTo, const String& path, const String& fileToCheckFor) | |||
| { | |||
| auto actualPath = path.replace ("${user.home}", File::getSpecialLocation (File::userHomeDirectory).getFullPathName()); | |||
| return relativeTo.getChildFile (actualPath + "/" + fileToCheckFor).existsAsFile(); | |||
| } | |||
| Value StoredSettings::getGlobalPath (const Identifier& key, DependencyPathOS os) | |||
| Value StoredSettings::getStoredPath (const Identifier& key) | |||
| { | |||
| auto v = projectDefaults.getPropertyAsValue (key, nullptr); | |||
| if (v.toString().isEmpty()) | |||
| { | |||
| auto defaultPath = getFallbackPath (key, os); | |||
| if (os == TargetOS::getThisOS()) | |||
| v = defaultPath; | |||
| } | |||
| v = getFallbackPathForOS (key, TargetOS::getThisOS()).toString(); | |||
| return v; | |||
| } | |||
| String StoredSettings::getFallbackPath (const Identifier& key, DependencyPathOS os) | |||
| Value StoredSettings::getFallbackPathForOS (const Identifier& key, DependencyPathOS os) | |||
| { | |||
| if (key == Ids::vst3Path) | |||
| return os == TargetOS::windows ? "c:\\SDKs\\VST_SDK\\VST3_SDK" | |||
| : "~/SDKs/VST_SDK/VST3_SDK"; | |||
| auto id = Identifier(); | |||
| if (key == Ids::rtasPath) | |||
| { | |||
| if (os == TargetOS::windows) return "c:\\SDKs\\PT_90_SDK"; | |||
| if (os == TargetOS::osx) return "~/SDKs/PT_90_SDK"; | |||
| if (os == TargetOS::osx) id = Ids::osxFallback; | |||
| else if (os == TargetOS::windows) id = Ids::windowsFallback; | |||
| else if (os == TargetOS::linux) id = Ids::linuxFallback; | |||
| // no RTAS on this OS! | |||
| if (id == Identifier()) | |||
| jassertfalse; | |||
| return {}; | |||
| } | |||
| if (key == Ids::aaxPath) | |||
| { | |||
| if (os == TargetOS::windows) return "c:\\SDKs\\AAX"; | |||
| if (os == TargetOS::osx) return "~/SDKs/AAX" ; | |||
| auto v = fallbackPaths.getOrCreateChildWithName (id, nullptr) | |||
| .getPropertyAsValue (key, nullptr); | |||
| // no AAX on this OS! | |||
| jassertfalse; | |||
| return {}; | |||
| if (v.toString().isEmpty()) | |||
| { | |||
| 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 = (os == TargetOS::windows ? "C:\\SDKs\\VST_SDK\\VST3_SDK" | |||
| : "~/SDKs/VST_SDK/VST3_SDK"); | |||
| } | |||
| 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 jassertfalse; // 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 jassertfalse; // 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"; | |||
| } | |||
| } | |||
| if (key == Ids::androidSDKPath) | |||
| return "${user.home}/Library/Android/sdk"; | |||
| if (key == Ids::androidNDKPath) | |||
| return "${user.home}/Library/Android/sdk/ndk-bundle"; | |||
| return v; | |||
| } | |||
| // didn't recognise the key provided! | |||
| jassertfalse; | |||
| return {}; | |||
| static bool doesSDKPathContainFile (const File& relativeTo, const String& path, const String& fileToCheckFor) | |||
| { | |||
| 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) | |||
| @@ -317,6 +338,14 @@ bool StoredSettings::isGlobalPathValid (const File& relativeTo, const Identifier | |||
| fileToCheckFor = "ndk-depends"; | |||
| #endif | |||
| } | |||
| else if (key == Ids::defaultJuceModulePath) | |||
| { | |||
| fileToCheckFor = "juce_core"; | |||
| } | |||
| else if (key == Ids::defaultUserModulePath) | |||
| { | |||
| fileToCheckFor = {}; | |||
| } | |||
| else | |||
| { | |||
| // didn't recognise the key provided! | |||
| @@ -62,23 +62,27 @@ public: | |||
| //============================================================================== | |||
| AppearanceSettings appearance; | |||
| StringArray monospacedFontNames; | |||
| //============================================================================== | |||
| Value getGlobalPath (const Identifier& key, DependencyPathOS); | |||
| String getFallbackPath (const Identifier& key, DependencyPathOS); | |||
| Value getStoredPath (const Identifier& key); | |||
| Value getFallbackPathForOS (const Identifier& key, DependencyPathOS); | |||
| bool isGlobalPathValid (const File& relativeTo, const Identifier& key, const String& path); | |||
| private: | |||
| OwnedArray<PropertiesFile> propertyFiles; | |||
| ValueTree projectDefaults; | |||
| ValueTree fallbackPaths; | |||
| void changed() | |||
| void changed (bool isProjectDefaults) | |||
| { | |||
| ScopedPointer<XmlElement> data (projectDefaults.createXml()); | |||
| propertyFiles.getUnchecked (0)->setValue ("PROJECT_DEFAULT_SETTINGS", data); | |||
| ScopedPointer<XmlElement> data (isProjectDefaults ? projectDefaults.createXml() | |||
| : fallbackPaths.createXml()); | |||
| propertyFiles.getUnchecked (0)->setValue (isProjectDefaults ? "PROJECT_DEFAULT_SETTINGS" | |||
| : "FALLBACK_PATHS", | |||
| data); | |||
| } | |||
| void updateGlobalPreferences(); | |||
| @@ -91,11 +95,11 @@ private: | |||
| void updateOldProjectSettingsFiles(); | |||
| //============================================================================== | |||
| void valueTreePropertyChanged (ValueTree&, const Identifier&) override { changed(); } | |||
| void valueTreeChildAdded (ValueTree&, ValueTree&) override { changed(); } | |||
| void valueTreeChildRemoved (ValueTree&, ValueTree&, int) override { changed(); } | |||
| void valueTreeChildOrderChanged (ValueTree&, int, int) override { changed(); } | |||
| void valueTreeParentChanged (ValueTree&) override { changed(); } | |||
| 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); } | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StoredSettings) | |||
| }; | |||
| @@ -103,7 +103,8 @@ struct NewProjectWizard | |||
| //============================================================================== | |||
| Project* runWizard (WizardComp& wc, | |||
| const String& projectName, | |||
| const File& target) | |||
| const File& target, | |||
| bool useGlobalPath) | |||
| { | |||
| ownerWizardComp = &wc; | |||
| appTitle = projectName; | |||
| @@ -140,7 +141,7 @@ struct NewProjectWizard | |||
| return nullptr; | |||
| addExporters (*project, wc); | |||
| addDefaultModules (*project, false); | |||
| addDefaultModules (*project, useGlobalPath); | |||
| if (project->save (false, true) != FileBasedDocument::savedOk) | |||
| return nullptr; | |||
| @@ -173,7 +174,7 @@ struct NewProjectWizard | |||
| failedFiles.add (getSourceFilesFolder().getFullPathName()); | |||
| } | |||
| void addDefaultModules (Project& project, bool areModulesCopiedLocally) | |||
| void addDefaultModules (Project& project, bool useGlobalPath) | |||
| { | |||
| StringArray mods (getDefaultModules()); | |||
| @@ -182,7 +183,7 @@ struct NewProjectWizard | |||
| for (int i = 0; i < mods.size(); ++i) | |||
| if (const ModuleDescription* info = list.getModuleWithID (mods[i])) | |||
| project.getModules().addModule (info->moduleFolder, areModulesCopiedLocally); | |||
| project.getModules().addModule (info->moduleFolder, false, useGlobalPath); | |||
| } | |||
| void addExporters (Project& project, WizardComp& wizardComp) | |||
| @@ -35,10 +35,11 @@ public: | |||
| ModulesFolderPathBox (File initialFileOrDirectory) | |||
| : currentPathBox ("currentPathBox"), | |||
| openFolderButton (TRANS("...")), | |||
| modulesLabel (String(), TRANS("Modules Folder") + ":") | |||
| modulesLabel (String(), TRANS("Modules Folder") + ":"), | |||
| useGlobalPathsToggle ("Use global module path") | |||
| { | |||
| if (initialFileOrDirectory == File()) | |||
| initialFileOrDirectory = findDefaultModulesFolder(); | |||
| initialFileOrDirectory = EnabledModuleList::findGlobalModulesFolder(); | |||
| setModulesFolder (initialFileOrDirectory); | |||
| @@ -52,15 +53,24 @@ public: | |||
| addAndMakeVisible (modulesLabel); | |||
| modulesLabel.attachToComponent (¤tPathBox, true); | |||
| addAndMakeVisible (useGlobalPathsToggle); | |||
| useGlobalPathsToggle.addListener (this); | |||
| useGlobalPathsToggle.setToggleState (true, sendNotification); | |||
| } | |||
| void resized() override | |||
| { | |||
| auto r = getLocalBounds(); | |||
| auto b = getLocalBounds(); | |||
| auto topSlice = b.removeFromTop (b.getHeight() / 2); | |||
| openFolderButton.setBounds (topSlice.removeFromRight (30)); | |||
| modulesLabel.setBounds (topSlice.removeFromLeft (110)); | |||
| currentPathBox.setBounds (topSlice); | |||
| openFolderButton.setBounds (r.removeFromRight (30)); | |||
| modulesLabel.setBounds (r.removeFromLeft (110)); | |||
| currentPathBox.setBounds (r); | |||
| b.removeFromTop (5); | |||
| useGlobalPathsToggle.setBounds (b.translated (20, 0)); | |||
| } | |||
| static bool selectJuceFolder (File& result) | |||
| @@ -68,7 +78,7 @@ public: | |||
| for (;;) | |||
| { | |||
| FileChooser fc ("Select your JUCE modules folder...", | |||
| findDefaultModulesFolder(), | |||
| EnabledModuleList::findGlobalModulesFolder(), | |||
| "*"); | |||
| if (! fc.browseForDirectory()) | |||
| @@ -104,9 +114,21 @@ public: | |||
| } | |||
| } | |||
| void buttonClicked (Button*) override | |||
| void buttonClicked (Button* b) override | |||
| { | |||
| selectJuceFolder(); | |||
| if (b == &openFolderButton) | |||
| { | |||
| selectJuceFolder(); | |||
| } | |||
| else if (b == &useGlobalPathsToggle) | |||
| { | |||
| isUsingGlobalPaths = useGlobalPathsToggle.getToggleState(); | |||
| currentPathBox.setEnabled (! isUsingGlobalPaths); | |||
| openFolderButton.setEnabled (! isUsingGlobalPaths); | |||
| modulesLabel.setEnabled (! isUsingGlobalPaths); | |||
| } | |||
| } | |||
| void comboBoxChanged (ComboBox*) override | |||
| @@ -115,11 +137,13 @@ public: | |||
| } | |||
| File modulesFolder; | |||
| bool isUsingGlobalPaths; | |||
| private: | |||
| ComboBox currentPathBox; | |||
| TextButton openFolderButton; | |||
| Label modulesLabel; | |||
| ToggleButton useGlobalPathsToggle; | |||
| }; | |||
| @@ -280,7 +304,7 @@ public: | |||
| WizardComp() | |||
| : platformTargets(), | |||
| projectName (TRANS("Project name")), | |||
| modulesPathBox (findDefaultModulesFolder()) | |||
| modulesPathBox (EnabledModuleList::findGlobalModulesFolder()) | |||
| { | |||
| setOpaque (false); | |||
| @@ -355,7 +379,7 @@ public: | |||
| filesToCreate.setBounds (right.removeFromTop (22).withTrimmedLeft (150)); | |||
| right.removeFromTop (20); | |||
| modulesPathBox.setBounds (right.removeFromTop (22)); | |||
| modulesPathBox.setBounds (right.removeFromTop (50)); | |||
| right.removeFromTop (20); | |||
| targetsOutline.setBounds (right); | |||
| @@ -404,14 +428,27 @@ public: | |||
| return; | |||
| } | |||
| wizard->modulesFolder = modulesPathBox.modulesFolder; | |||
| wizard->modulesFolder = modulesPathBox.isUsingGlobalPaths ? File (getAppSettings().getStoredPath (Ids::defaultJuceModulePath).toString()) | |||
| : modulesPathBox.modulesFolder; | |||
| if (! isJuceModulesFolder (wizard->modulesFolder)) | |||
| { | |||
| if (modulesPathBox.isUsingGlobalPaths) | |||
| AlertWindow::showMessageBox (AlertWindow::AlertIconType::WarningIcon, "Invalid Global Path", | |||
| "Your global JUCE module search path is invalid. Please select the folder containing your JUCE modules " | |||
| "to set as the default path."); | |||
| if (! wizard->selectJuceFolder()) | |||
| return; | |||
| if (modulesPathBox.isUsingGlobalPaths) | |||
| getAppSettings().getStoredPath (Ids::defaultJuceModulePath).setValue (wizard->modulesFolder.getFullPathName()); | |||
| } | |||
| if (ScopedPointer<Project> project = wizard->runWizard (*this, projectName.getText(), | |||
| fileBrowser.getSelectedFile (0))) | |||
| fileBrowser.getSelectedFile (0), | |||
| modulesPathBox.isUsingGlobalPaths)) | |||
| mw->setProject (project.release()); | |||
| } | |||
| } | |||