1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

Projucer: Implement PIPGenerator

This commit is contained in:
ed 2018-03-15 11:11:23 +00:00
parent fa02112614
commit 47af78fe0b
31 changed files with 1256 additions and 457 deletions

View file

@ -101,6 +101,7 @@ OBJECTS_APP := \
$(JUCE_OBJDIR)/jucer_CompileEngineClient_aee8c99c.o \ $(JUCE_OBJDIR)/jucer_CompileEngineClient_aee8c99c.o \
$(JUCE_OBJDIR)/jucer_CompileEngineServer_5d8914.o \ $(JUCE_OBJDIR)/jucer_CompileEngineServer_5d8914.o \
$(JUCE_OBJDIR)/jucer_DownloadCompileEngineThread_19bb4bb3.o \ $(JUCE_OBJDIR)/jucer_DownloadCompileEngineThread_19bb4bb3.o \
$(JUCE_OBJDIR)/jucer_HeaderComponent_1ebf72ba.o \
$(JUCE_OBJDIR)/jucer_Module_3f7666a5.o \ $(JUCE_OBJDIR)/jucer_Module_3f7666a5.o \
$(JUCE_OBJDIR)/jucer_Project_c131864a.o \ $(JUCE_OBJDIR)/jucer_Project_c131864a.o \
$(JUCE_OBJDIR)/jucer_ProjectExporter_cf377b25.o \ $(JUCE_OBJDIR)/jucer_ProjectExporter_cf377b25.o \
@ -304,6 +305,11 @@ $(JUCE_OBJDIR)/jucer_DownloadCompileEngineThread_19bb4bb3.o: ../../Source/LiveBu
@echo "Compiling jucer_DownloadCompileEngineThread.cpp" @echo "Compiling jucer_DownloadCompileEngineThread.cpp"
$(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<" $(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<"
$(JUCE_OBJDIR)/jucer_HeaderComponent_1ebf72ba.o: ../../Source/Project/UI/jucer_HeaderComponent.cpp
-$(V_AT)mkdir -p $(JUCE_OBJDIR)
@echo "Compiling jucer_HeaderComponent.cpp"
$(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<"
$(JUCE_OBJDIR)/jucer_Module_3f7666a5.o: ../../Source/Project/jucer_Module.cpp $(JUCE_OBJDIR)/jucer_Module_3f7666a5.o: ../../Source/Project/jucer_Module.cpp
-$(V_AT)mkdir -p $(JUCE_OBJDIR) -$(V_AT)mkdir -p $(JUCE_OBJDIR)
@echo "Compiling jucer_Module.cpp" @echo "Compiling jucer_Module.cpp"

View file

@ -57,6 +57,7 @@
D25EBE02B55DB244BE0D5635 = {isa = PBXBuildFile; fileRef = DE3E6B2614229FAD56D50770; }; D25EBE02B55DB244BE0D5635 = {isa = PBXBuildFile; fileRef = DE3E6B2614229FAD56D50770; };
85E7FCB0516EFF853FA7B380 = {isa = PBXBuildFile; fileRef = D2FE76E4CF003856278343CC; }; 85E7FCB0516EFF853FA7B380 = {isa = PBXBuildFile; fileRef = D2FE76E4CF003856278343CC; };
CC6C4D351BA9B473E5F95791 = {isa = PBXBuildFile; fileRef = ADA538034910F52FDD2DC88D; }; CC6C4D351BA9B473E5F95791 = {isa = PBXBuildFile; fileRef = ADA538034910F52FDD2DC88D; };
05A08E366EBF8D650974E695 = {isa = PBXBuildFile; fileRef = 516D6D7C564DD5DF5C15CB06; };
3FCA61C401007B243E2E9035 = {isa = PBXBuildFile; fileRef = F797071D88542C813CF7222A; }; 3FCA61C401007B243E2E9035 = {isa = PBXBuildFile; fileRef = F797071D88542C813CF7222A; };
30B921C38DCEE787B294B746 = {isa = PBXBuildFile; fileRef = BAC43B20E14A340CCF14119C; }; 30B921C38DCEE787B294B746 = {isa = PBXBuildFile; fileRef = BAC43B20E14A340CCF14119C; };
244567D3AE2E417A8CB2B95E = {isa = PBXBuildFile; fileRef = C3BB9F92B02B06D04A73794C; }; 244567D3AE2E417A8CB2B95E = {isa = PBXBuildFile; fileRef = C3BB9F92B02B06D04A73794C; };
@ -180,6 +181,7 @@
50498FF6EA3901CBD58223B3 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_ObjectTypes.h"; path = "../../Source/ComponentEditor/jucer_ObjectTypes.h"; sourceTree = "SOURCE_ROOT"; }; 50498FF6EA3901CBD58223B3 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_ObjectTypes.h"; path = "../../Source/ComponentEditor/jucer_ObjectTypes.h"; sourceTree = "SOURCE_ROOT"; };
512D80BE12634967A085A1DC = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "jucer_PaintElement.cpp"; path = "../../Source/ComponentEditor/PaintElements/jucer_PaintElement.cpp"; sourceTree = "SOURCE_ROOT"; }; 512D80BE12634967A085A1DC = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "jucer_PaintElement.cpp"; path = "../../Source/ComponentEditor/PaintElements/jucer_PaintElement.cpp"; sourceTree = "SOURCE_ROOT"; };
514F2FAFDBF535AC03FA2E6C = {isa = PBXFileReference; lastKnownFileType = file.svg; name = "background_logo.svg"; path = "../../Source/BinaryData/Icons/background_logo.svg"; sourceTree = "SOURCE_ROOT"; }; 514F2FAFDBF535AC03FA2E6C = {isa = PBXFileReference; lastKnownFileType = file.svg; name = "background_logo.svg"; path = "../../Source/BinaryData/Icons/background_logo.svg"; sourceTree = "SOURCE_ROOT"; };
516D6D7C564DD5DF5C15CB06 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "jucer_HeaderComponent.cpp"; path = "../../Source/Project/UI/jucer_HeaderComponent.cpp"; sourceTree = "SOURCE_ROOT"; };
51BC758EF5D33197CF543E67 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_DocumentEditorComponent.h"; path = "../../Source/CodeEditor/jucer_DocumentEditorComponent.h"; sourceTree = "SOURCE_ROOT"; }; 51BC758EF5D33197CF543E67 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_DocumentEditorComponent.h"; path = "../../Source/CodeEditor/jucer_DocumentEditorComponent.h"; sourceTree = "SOURCE_ROOT"; };
51CBE59779A36D1B80B26974 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "jucer_LicenseController.cpp"; path = "../../Source/Licenses/jucer_LicenseController.cpp"; sourceTree = "SOURCE_ROOT"; }; 51CBE59779A36D1B80B26974 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "jucer_LicenseController.cpp"; path = "../../Source/Licenses/jucer_LicenseController.cpp"; sourceTree = "SOURCE_ROOT"; };
5432B7B9B2CF2EAEC8B66D5C = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_UtilityFunctions.h"; path = "../../Source/ComponentEditor/jucer_UtilityFunctions.h"; sourceTree = "SOURCE_ROOT"; }; 5432B7B9B2CF2EAEC8B66D5C = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_UtilityFunctions.h"; path = "../../Source/ComponentEditor/jucer_UtilityFunctions.h"; sourceTree = "SOURCE_ROOT"; };
@ -633,6 +635,7 @@
236D186F5A6536C59D6E751C, 236D186F5A6536C59D6E751C,
32ECBC08D903418CA0825870, 32ECBC08D903418CA0825870,
A509BC22854D50E4C786EB32, A509BC22854D50E4C786EB32,
516D6D7C564DD5DF5C15CB06,
16751E04B0F3737BDF52CEB4, 16751E04B0F3737BDF52CEB4,
B3528C08B84CBC950252EA69, B3528C08B84CBC950252EA69,
1B0F18E1D96F727C062B05FA, 1B0F18E1D96F727C062B05FA,
@ -964,6 +967,7 @@
D25EBE02B55DB244BE0D5635, D25EBE02B55DB244BE0D5635,
85E7FCB0516EFF853FA7B380, 85E7FCB0516EFF853FA7B380,
CC6C4D351BA9B473E5F95791, CC6C4D351BA9B473E5F95791,
05A08E366EBF8D650974E695,
3FCA61C401007B243E2E9035, 3FCA61C401007B243E2E9035,
30B921C38DCEE787B294B746, 30B921C38DCEE787B294B746,
244567D3AE2E417A8CB2B95E, 244567D3AE2E417A8CB2B95E,

View file

@ -226,6 +226,7 @@
<ClCompile Include="..\..\Source\LiveBuildEngine\jucer_CompileEngineClient.cpp"/> <ClCompile Include="..\..\Source\LiveBuildEngine\jucer_CompileEngineClient.cpp"/>
<ClCompile Include="..\..\Source\LiveBuildEngine\jucer_CompileEngineServer.cpp"/> <ClCompile Include="..\..\Source\LiveBuildEngine\jucer_CompileEngineServer.cpp"/>
<ClCompile Include="..\..\Source\LiveBuildEngine\jucer_DownloadCompileEngineThread.cpp"/> <ClCompile Include="..\..\Source\LiveBuildEngine\jucer_DownloadCompileEngineThread.cpp"/>
<ClCompile Include="..\..\Source\Project\UI\jucer_HeaderComponent.cpp"/>
<ClCompile Include="..\..\Source\Project\UI\jucer_ProjectContentComponent.cpp"> <ClCompile Include="..\..\Source\Project\UI\jucer_ProjectContentComponent.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>

View file

@ -442,6 +442,9 @@
<ClCompile Include="..\..\Source\LiveBuildEngine\jucer_DownloadCompileEngineThread.cpp"> <ClCompile Include="..\..\Source\LiveBuildEngine\jucer_DownloadCompileEngineThread.cpp">
<Filter>Projucer\LiveBuildEngine</Filter> <Filter>Projucer\LiveBuildEngine</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\Source\Project\UI\jucer_HeaderComponent.cpp">
<Filter>Projucer\Project\UI</Filter>
</ClCompile>
<ClCompile Include="..\..\Source\Project\UI\jucer_ProjectContentComponent.cpp"> <ClCompile Include="..\..\Source\Project\UI\jucer_ProjectContentComponent.cpp">
<Filter>Projucer\Project\UI</Filter> <Filter>Projucer\Project\UI</Filter>
</ClCompile> </ClCompile>

View file

@ -226,6 +226,7 @@
<ClCompile Include="..\..\Source\LiveBuildEngine\jucer_CompileEngineClient.cpp"/> <ClCompile Include="..\..\Source\LiveBuildEngine\jucer_CompileEngineClient.cpp"/>
<ClCompile Include="..\..\Source\LiveBuildEngine\jucer_CompileEngineServer.cpp"/> <ClCompile Include="..\..\Source\LiveBuildEngine\jucer_CompileEngineServer.cpp"/>
<ClCompile Include="..\..\Source\LiveBuildEngine\jucer_DownloadCompileEngineThread.cpp"/> <ClCompile Include="..\..\Source\LiveBuildEngine\jucer_DownloadCompileEngineThread.cpp"/>
<ClCompile Include="..\..\Source\Project\UI\jucer_HeaderComponent.cpp"/>
<ClCompile Include="..\..\Source\Project\UI\jucer_ProjectContentComponent.cpp"> <ClCompile Include="..\..\Source\Project\UI\jucer_ProjectContentComponent.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>

View file

@ -442,6 +442,9 @@
<ClCompile Include="..\..\Source\LiveBuildEngine\jucer_DownloadCompileEngineThread.cpp"> <ClCompile Include="..\..\Source\LiveBuildEngine\jucer_DownloadCompileEngineThread.cpp">
<Filter>Projucer\LiveBuildEngine</Filter> <Filter>Projucer\LiveBuildEngine</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\Source\Project\UI\jucer_HeaderComponent.cpp">
<Filter>Projucer\Project\UI</Filter>
</ClCompile>
<ClCompile Include="..\..\Source\Project\UI\jucer_ProjectContentComponent.cpp"> <ClCompile Include="..\..\Source\Project\UI\jucer_ProjectContentComponent.cpp">
<Filter>Projucer\Project\UI</Filter> <Filter>Projucer\Project\UI</Filter>
</ClCompile> </ClCompile>

View file

@ -226,6 +226,7 @@
<ClCompile Include="..\..\Source\LiveBuildEngine\jucer_CompileEngineClient.cpp"/> <ClCompile Include="..\..\Source\LiveBuildEngine\jucer_CompileEngineClient.cpp"/>
<ClCompile Include="..\..\Source\LiveBuildEngine\jucer_CompileEngineServer.cpp"/> <ClCompile Include="..\..\Source\LiveBuildEngine\jucer_CompileEngineServer.cpp"/>
<ClCompile Include="..\..\Source\LiveBuildEngine\jucer_DownloadCompileEngineThread.cpp"/> <ClCompile Include="..\..\Source\LiveBuildEngine\jucer_DownloadCompileEngineThread.cpp"/>
<ClCompile Include="..\..\Source\Project\UI\jucer_HeaderComponent.cpp"/>
<ClCompile Include="..\..\Source\Project\UI\jucer_ProjectContentComponent.cpp"> <ClCompile Include="..\..\Source\Project\UI\jucer_ProjectContentComponent.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>

View file

@ -442,6 +442,9 @@
<ClCompile Include="..\..\Source\LiveBuildEngine\jucer_DownloadCompileEngineThread.cpp"> <ClCompile Include="..\..\Source\LiveBuildEngine\jucer_DownloadCompileEngineThread.cpp">
<Filter>Projucer\LiveBuildEngine</Filter> <Filter>Projucer\LiveBuildEngine</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\Source\Project\UI\jucer_HeaderComponent.cpp">
<Filter>Projucer\Project\UI</Filter>
</ClCompile>
<ClCompile Include="..\..\Source\Project\UI\jucer_ProjectContentComponent.cpp"> <ClCompile Include="..\..\Source\Project\UI\jucer_ProjectContentComponent.cpp">
<Filter>Projucer\Project\UI</Filter> <Filter>Projucer\Project\UI</Filter>
</ClCompile> </ClCompile>

View file

@ -542,6 +542,8 @@
resource="0" file="Source/Project/UI/jucer_ContentViewComponents.h"/> resource="0" file="Source/Project/UI/jucer_ContentViewComponents.h"/>
<FILE id="wFypDd" name="jucer_FileGroupInformationComponent.h" compile="0" <FILE id="wFypDd" name="jucer_FileGroupInformationComponent.h" compile="0"
resource="0" file="Source/Project/UI/jucer_FileGroupInformationComponent.h"/> resource="0" file="Source/Project/UI/jucer_FileGroupInformationComponent.h"/>
<FILE id="P6wdlv" name="jucer_HeaderComponent.cpp" compile="1" resource="0"
file="Source/Project/UI/jucer_HeaderComponent.cpp"/>
<FILE id="QVjJdU" name="jucer_HeaderComponent.h" compile="0" resource="0" <FILE id="QVjJdU" name="jucer_HeaderComponent.h" compile="0" resource="0"
file="Source/Project/UI/jucer_HeaderComponent.h"/> file="Source/Project/UI/jucer_HeaderComponent.h"/>
<FILE id="dN0Xzo" name="jucer_ModulesInformationComponent.h" compile="0" <FILE id="dN0Xzo" name="jucer_ModulesInformationComponent.h" compile="0"

View file

@ -28,25 +28,12 @@
//============================================================================== //==============================================================================
class GlobalSearchPathsWindowComponent : public Component class GlobalPathsWindowComponent : public Component
{ {
public: public:
GlobalSearchPathsWindowComponent() GlobalPathsWindowComponent()
: modulesLabel ("modulesLabel", "Modules"),
sdksLabel ("sdksLabel", "SDKs"),
cLionLabel ("cLionLabel", "CLion")
{ {
addAndMakeVisible (modulesLabel); addLabelsAndSetProperties();
addAndMakeVisible (sdksLabel);
addAndMakeVisible (cLionLabel);
modulesLabel.setFont (Font (18.0f, Font::FontStyleFlags::bold));
sdksLabel .setFont (Font (18.0f, Font::FontStyleFlags::bold));
cLionLabel .setFont (Font (18.0f, Font::FontStyleFlags::bold));
modulesLabel.setJustificationType (Justification::centredLeft);
sdksLabel .setJustificationType (Justification::centredLeft);
cLionLabel .setJustificationType (Justification::centredLeft);
addAndMakeVisible (info); addAndMakeVisible (info);
info.setInfoToDisplay ("Use this dropdown to set the global paths for different OSes. " info.setInfoToDisplay ("Use this dropdown to set the global paths for different OSes. "
@ -59,7 +46,11 @@ public:
osSelector.addItem ("Windows", 2); osSelector.addItem ("Windows", 2);
osSelector.addItem ("Linux", 3); osSelector.addItem ("Linux", 3);
osSelector.onChange = [this] { updateFilePathPropertyComponents(); }; osSelector.onChange = [this]
{
addLabelsAndSetProperties();
updateFilePathPropertyComponents();
};
auto os = TargetOS::getThisOS(); auto os = TargetOS::getThisOS();
@ -85,40 +76,33 @@ public:
info.setBounds (osSelector.getBounds().withWidth (osSelector.getHeight()).translated ((osSelector.getWidth() + 5), 0).reduced (2)); info.setBounds (osSelector.getBounds().withWidth (osSelector.getHeight()).translated ((osSelector.getWidth() + 5), 0).reduced (2));
modulesLabel.setBounds (b.removeFromTop (20)); int labelIndex = 0;
b.removeFromTop (20); for (auto* pathComp : pathPropertyComponents)
auto thisOS = TargetOS::getThisOS();
auto selectedOS = getSelectedOS();
const int numComps = pathPropertyComponents.size();
for (int i = 0; i < numComps; ++i)
{ {
pathPropertyComponents[i]->setBounds (b.removeFromTop (pathPropertyComponents[i]->getPreferredHeight())); if (pathComp == nullptr)
b.removeFromTop (5);
if (i == 1)
{ {
b.removeFromTop (15); b.removeFromTop (15);
sdksLabel.setBounds (b.removeFromTop (20)); pathPropertyLabels.getUnchecked (labelIndex++)->setBounds (b.removeFromTop (20));
b.removeFromTop (20); b.removeFromTop (20);
} }
else
if (selectedOS == thisOS && i == numComps - 2)
{ {
b.removeFromTop (15); pathComp->setBounds (b.removeFromTop (pathComp->getPreferredHeight()));
cLionLabel.setBounds (b.removeFromTop (20)); b.removeFromTop (5);
b.removeFromTop (20);
} }
} }
} }
private: private:
Label modulesLabel, sdksLabel, cLionLabel; OwnedArray<Label> pathPropertyLabels;
OwnedArray<PropertyComponent> pathPropertyComponents; OwnedArray<PropertyComponent> pathPropertyComponents;
ComboBox osSelector; ComboBox osSelector;
InfoButton info; InfoButton info;
//==============================================================================
bool isSelectedOSThisOS() { return TargetOS::getThisOS() == getSelectedOS(); }
TargetOS::OS getSelectedOS() const TargetOS::OS getSelectedOS() const
{ {
auto selectedOS = TargetOS::unknown; auto selectedOS = TargetOS::unknown;
@ -138,27 +122,28 @@ private:
{ {
pathPropertyComponents.clear(); pathPropertyComponents.clear();
const auto thisOS = TargetOS::getThisOS();
const auto selectedOS = getSelectedOS();
auto& settings = getAppSettings(); auto& settings = getAppSettings();
if (selectedOS == thisOS) if (isSelectedOSThisOS())
{ {
pathPropertyComponents.add (nullptr);
addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (settings.getStoredPath (Ids::defaultJuceModulePath), addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (settings.getStoredPath (Ids::defaultJuceModulePath),
"JUCE Modules", true))); "JUCE Modules", true)));
addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (settings.getStoredPath (Ids::defaultUserModulePath), addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (settings.getStoredPath (Ids::defaultUserModulePath),
"User Modules", true, {}, {}, true))); "User Modules", true, {}, {}, true)));
pathPropertyComponents.add (nullptr);
addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (settings.getStoredPath (Ids::vst3Path), addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (settings.getStoredPath (Ids::vst3Path),
"VST3 SDK", true))); "VST3 SDK", true)));
if (selectedOS == TargetOS::linux) if (getSelectedOS() == TargetOS::linux)
{ {
addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (Value(), "RTAS SDK", true))); addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent ({}, "RTAS SDK", true)));
pathPropertyComponents.getLast()->setEnabled (false); pathPropertyComponents.getLast()->setEnabled (false);
addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (Value(), "AAX SDK", true))); addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent ({}, "AAX SDK", true)));
pathPropertyComponents.getLast()->setEnabled (false); pathPropertyComponents.getLast()->setEnabled (false);
} }
else else
@ -174,6 +159,8 @@ private:
addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (settings.getStoredPath (Ids::androidNDKPath), addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (settings.getStoredPath (Ids::androidNDKPath),
"Android NDK", true))); "Android NDK", true)));
pathPropertyComponents.add (nullptr);
#if JUCE_MAC #if JUCE_MAC
String exeLabel ("app"); String exeLabel ("app");
#elif JUCE_WINDOWS #elif JUCE_WINDOWS
@ -186,13 +173,18 @@ private:
} }
else else
{ {
auto selectedOS = getSelectedOS();
auto maxChars = 1024; auto maxChars = 1024;
pathPropertyComponents.add (nullptr);
addAndMakeVisible (pathPropertyComponents.add (new TextPropertyComponent (settings.getFallbackPathForOS (Ids::defaultJuceModulePath, selectedOS), addAndMakeVisible (pathPropertyComponents.add (new TextPropertyComponent (settings.getFallbackPathForOS (Ids::defaultJuceModulePath, selectedOS),
"JUCE Modules", maxChars, false))); "JUCE Modules", maxChars, false)));
addAndMakeVisible (pathPropertyComponents.add (new TextPropertyComponent (settings.getFallbackPathForOS (Ids::defaultUserModulePath, selectedOS), addAndMakeVisible (pathPropertyComponents.add (new TextPropertyComponent (settings.getFallbackPathForOS (Ids::defaultUserModulePath, selectedOS),
"User Modules", maxChars, false))); "User Modules", maxChars, false)));
pathPropertyComponents.add (nullptr);
addAndMakeVisible (pathPropertyComponents.add (new TextPropertyComponent (settings.getFallbackPathForOS (Ids::vst3Path, selectedOS), addAndMakeVisible (pathPropertyComponents.add (new TextPropertyComponent (settings.getFallbackPathForOS (Ids::vst3Path, selectedOS),
"VST3 SDK", maxChars, false))); "VST3 SDK", maxChars, false)));
@ -207,19 +199,35 @@ private:
else else
{ {
addAndMakeVisible (pathPropertyComponents.add (new TextPropertyComponent (settings.getFallbackPathForOS (Ids::rtasPath, selectedOS), addAndMakeVisible (pathPropertyComponents.add (new TextPropertyComponent (settings.getFallbackPathForOS (Ids::rtasPath, selectedOS),
"RTAS SDK", maxChars, false))); "RTAS SDK", maxChars, false)));
addAndMakeVisible (pathPropertyComponents.add (new TextPropertyComponent (settings.getFallbackPathForOS (Ids::aaxPath, selectedOS), addAndMakeVisible (pathPropertyComponents.add (new TextPropertyComponent (settings.getFallbackPathForOS (Ids::aaxPath, selectedOS),
"AAX SDK", maxChars, false))); "AAX SDK", maxChars, false)));
} }
addAndMakeVisible (pathPropertyComponents.add (new TextPropertyComponent (settings.getFallbackPathForOS (Ids::androidSDKPath, selectedOS), addAndMakeVisible (pathPropertyComponents.add (new TextPropertyComponent (settings.getFallbackPathForOS (Ids::androidSDKPath, selectedOS),
"Android SDK", maxChars, false))); "Android SDK", maxChars, false)));
addAndMakeVisible (pathPropertyComponents.add (new TextPropertyComponent (settings.getFallbackPathForOS (Ids::androidNDKPath, selectedOS), addAndMakeVisible (pathPropertyComponents.add (new TextPropertyComponent (settings.getFallbackPathForOS (Ids::androidNDKPath, selectedOS),
"Android NDK", maxChars, false))); "Android NDK", maxChars, false)));
} }
resized(); resized();
} }
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GlobalSearchPathsWindowComponent) void addLabelsAndSetProperties()
{
pathPropertyLabels.clear();
pathPropertyLabels.add (new Label ("modulesLabel", "Modules"));
pathPropertyLabels.add (new Label ("sdksLabel", "SDKs"));
pathPropertyLabels.add (new Label ("otherLabel", "Other"));
for (auto* l : pathPropertyLabels)
{
addAndMakeVisible (l);
l->setFont (Font (18.0f, Font::FontStyleFlags::bold));
l->setJustificationType (Justification::centredLeft);
}
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GlobalPathsWindowComponent)
}; };

View file

@ -224,6 +224,10 @@ void ProjucerApplication::shutdown()
LookAndFeel::setDefaultLookAndFeel (nullptr); LookAndFeel::setDefaultLookAndFeel (nullptr);
// clean up after ourselves and delete any temp project files that may have
// been created from PIPs
deleteTemporaryFiles();
if (! isRunningCommandLine) if (! isRunningCommandLine)
Logger::writeToLog ("Shutdown"); Logger::writeToLog ("Shutdown");
@ -332,7 +336,8 @@ enum
openWindowsBaseID = 300, openWindowsBaseID = 300,
activeDocumentsBaseID = 400, activeDocumentsBaseID = 400,
colourSchemeBaseID = 1000, colourSchemeBaseID = 1000,
codeEditorColourSchemeBaseID = 2000, codeEditorColourSchemeBaseID = 1500,
examplesBaseID = 2000,
}; };
MenuBarModel* ProjucerApplication::getMenuModel() MenuBarModel* ProjucerApplication::getMenuModel()
@ -362,6 +367,7 @@ void ProjucerApplication::createMenu (PopupMenu& menu, const String& menuName)
void ProjucerApplication::createFileMenu (PopupMenu& menu) void ProjucerApplication::createFileMenu (PopupMenu& menu)
{ {
menu.addCommandItem (commandManager, CommandIDs::newProject); menu.addCommandItem (commandManager, CommandIDs::newProject);
menu.addCommandItem (commandManager, CommandIDs::newProjectFromClipboard);
menu.addSeparator(); menu.addSeparator();
menu.addCommandItem (commandManager, CommandIDs::open); menu.addCommandItem (commandManager, CommandIDs::open);
@ -379,6 +385,13 @@ void ProjucerApplication::createFileMenu (PopupMenu& menu)
menu.addSubMenu ("Open Recent", recentFiles); menu.addSubMenu ("Open Recent", recentFiles);
} }
{
PopupMenu examples;
createExamplesPopupMenu (examples);
menu.addSubMenu ("Open Example", examples);
}
menu.addSeparator(); menu.addSeparator();
menu.addCommandItem (commandManager, CommandIDs::closeDocument); menu.addCommandItem (commandManager, CommandIDs::closeDocument);
menu.addCommandItem (commandManager, CommandIDs::saveDocument); menu.addCommandItem (commandManager, CommandIDs::saveDocument);
@ -554,6 +567,244 @@ void ProjucerApplication::createExtraAppleMenuItems (PopupMenu& menu)
menu.addCommandItem (commandManager, CommandIDs::showGlobalPathsWindow); menu.addCommandItem (commandManager, CommandIDs::showGlobalPathsWindow);
} }
void ProjucerApplication::createExamplesPopupMenu (PopupMenu& menu) noexcept
{
numExamples = 0;
for (auto& dir : getSortedExampleDirectories())
{
PopupMenu m;
for (auto& f : getSortedExampleFilesInDirectory (dir))
{
m.addItem (examplesBaseID + numExamples, f.getFileNameWithoutExtension());
++numExamples;
}
menu.addSubMenu (dir.getFileName(), m);
}
if (numExamples == 0)
{
menu.addCommandItem (commandManager, CommandIDs::showGlobalPathsWindow, "Set path to JUCE...");
}
else
{
menu.addSeparator();
menu.addCommandItem (commandManager, CommandIDs::launchDemoRunner);
}
}
Array<File> ProjucerApplication::getSortedExampleDirectories() const noexcept
{
Array<File> exampleDirectories;
auto examplesPath = getJUCEExamplesDirectoryPathFromGlobal();
if (! isValidJUCEExamplesDirectory (examplesPath))
return {};
DirectoryIterator iter (examplesPath, false, "*", File::findDirectories);
while (iter.next())
{
auto exampleDirectory = iter.getFile();
if (exampleDirectory.getFileName() != "DemoRunner" && exampleDirectory.getFileName() != "Resources")
exampleDirectories.add (exampleDirectory);
}
exampleDirectories.sort();
return exampleDirectories;
}
Array<File> ProjucerApplication::getSortedExampleFilesInDirectory (const File& directory) const noexcept
{
Array<File> exampleFiles;
DirectoryIterator iter (directory, false, "*.h", File::findFiles);
while (iter.next())
exampleFiles.add (iter.getFile());
exampleFiles.sort();
return exampleFiles;
}
bool ProjucerApplication::findWindowAndOpenPIP (const File& pip)
{
auto* window = mainWindowList.getFrontmostWindow();
bool shouldCloseWindow = false;
if (window == nullptr)
{
window = mainWindowList.getOrCreateEmptyWindow();
shouldCloseWindow = true;
}
if (window->tryToOpenPIP (pip))
return true;
if (shouldCloseWindow)
mainWindowList.closeWindow (window);
return false;
}
void ProjucerApplication::findAndLaunchExample (int selectedIndex)
{
File example;
for (auto& dir : getSortedExampleDirectories())
{
auto exampleFiles = getSortedExampleFilesInDirectory (dir);
if (selectedIndex < exampleFiles.size())
{
example = exampleFiles.getUnchecked (selectedIndex);
break;
}
selectedIndex -= exampleFiles.size();
}
// example doesn't exist?
jassert (example != File());
findWindowAndOpenPIP (example);
}
File ProjucerApplication::findDemoRunnerExecutable() const noexcept
{
auto buildsPath = getJUCEExamplesDirectoryPathFromGlobal().getChildFile ("DemoRunner").getChildFile ("Builds");
if (! buildsPath.exists())
return {};
String extension;
#if JUCE_MAC
auto osxBuildFolder = buildsPath.getChildFile ("MacOSX").getChildFile ("build");
auto demoRunnerExecutable = osxBuildFolder.getChildFile ("Release").getChildFile ("DemoRunner.app");
if (demoRunnerExecutable.exists())
return demoRunnerExecutable;
demoRunnerExecutable = osxBuildFolder.getChildFile ("Debug").getChildFile ("DemoRunner.app");
if (demoRunnerExecutable.exists())
return demoRunnerExecutable;
extension = ".app";
#elif JUCE_WINDOWS
auto windowsBuildFolder = buildsPath.getChildFile ("VisualStudio2017").getChildFile ("x64");
auto demoRunnerExecutable = windowsBuildFolder.getChildFile ("Release").getChildFile ("App").getChildFile ("DemoRunner.exe");
if (demoRunnerExecutable.existsAsFile())
return demoRunnerExecutable;
demoRunnerExecutable = windowsBuildFolder.getChildFile ("Debug").getChildFile ("App").getChildFile ("DemoRunner.exe");
if (demoRunnerExecutable.existsAsFile())
return demoRunnerExecutable;
extension = ".exe";
#elif JUCE_LINUX
auto linuxBuildFolder = buildsPath.getChildFile ("LinuxMakefile").getChildFile ("build");
auto demoRunnerExecutable = linuxBuildFolder.getChildFile ("DemoRunner");
if (demoRunnerExecutable.existsAsFile())
return demoRunnerExecutable;
extension = {};
#endif
auto precompiledFile = getJUCEExamplesDirectoryPathFromGlobal().getChildFile ("DemoRunner" + extension);
#if JUCE_MAC
if (precompiledFile.exists())
#else
if (precompiledFile.existsAsFile())
#endif
return precompiledFile;
return {};
}
File ProjucerApplication::findDemoRunnerProject() const noexcept
{
auto buildsPath = getJUCEExamplesDirectoryPathFromGlobal().getChildFile ("DemoRunner").getChildFile ("Builds");
if (! buildsPath.exists())
return {};
#if JUCE_MAC
auto file = buildsPath.getChildFile ("MacOSX").getChildFile ("DemoRunner.xcodeproj");
if (file.exists())
return file;
#elif JUCE_WINDOW
auto file = buildsPath.getChildFile ("VisualStudio2017").getChildFile ("DemoRunner.sln");
if (file.existsAsFile())
return file;
#elif JUCE_LINUX
auto file = buildsPath.getChildFile ("LinuxMakeFile").getChildFile ("Makefile");
if (file.existsAsFile())
return file;
#endif
return {};
}
void ProjucerApplication::launchDemoRunner()
{
if (findDemoRunnerExecutable() != File())
{
bool succeeded = true;
if (! findDemoRunnerExecutable().startAsProcess())
{
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, "Error", "There was an error opening the Demo Runner file.");
succeeded = false;
}
}
else if (findDemoRunnerProject() != File())
{
auto& lf = Desktop::getInstance().getDefaultLookAndFeel();
demoRunnerAlert = lf.createAlertWindow ("Open Project",
"Couldn't find a compiled version of the Demo Runner."
#if JUCE_LINUX
" Do you want to build it now?", "Build project", "Cancel",
#else
" Do you want to open the project?", "Open project", "Cancel",
#endif
{},
AlertWindow::QuestionIcon, 2,
mainWindowList.getFrontmostWindow (false));
demoRunnerAlert->enterModalState (true, ModalCallbackFunction::create ([this] (int retVal)
{
demoRunnerAlert.reset (nullptr);
if (retVal == 1)
{
auto projectFile = findDemoRunnerProject();
#if JUCE_LINUX
String command ("make -C " + projectFile.getParentDirectory().getFullPathName() + " CONFIG=Release -j3");
if (! makeProcess.start (command))
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, "Error", "Error building Demo Runner.");
#else
projectFile.startAsProcess();
#endif
}
}), false);
}
else
{
jassertfalse;
}
}
void ProjucerApplication::handleMainMenuCommand (int menuItemID) void ProjucerApplication::handleMainMenuCommand (int menuItemID)
{ {
if (menuItemID >= recentProjectsBaseID && menuItemID < (recentProjectsBaseID + 100)) if (menuItemID >= recentProjectsBaseID && menuItemID < (recentProjectsBaseID + 100))
@ -586,6 +837,10 @@ void ProjucerApplication::handleMainMenuCommand (int menuItemID)
{ {
showEditorColourSchemeWindow(); showEditorColourSchemeWindow();
} }
else if (menuItemID >= examplesBaseID && menuItemID < (examplesBaseID + numExamples))
{
findAndLaunchExample (menuItemID - examplesBaseID);
}
else else
{ {
handleGUIEditorMenuCommand (menuItemID); handleGUIEditorMenuCommand (menuItemID);
@ -598,7 +853,9 @@ void ProjucerApplication::getAllCommands (Array <CommandID>& commands)
JUCEApplication::getAllCommands (commands); JUCEApplication::getAllCommands (commands);
const CommandID ids[] = { CommandIDs::newProject, const CommandID ids[] = { CommandIDs::newProject,
CommandIDs::newProjectFromClipboard,
CommandIDs::open, CommandIDs::open,
CommandIDs::launchDemoRunner,
CommandIDs::closeAllWindows, CommandIDs::closeAllWindows,
CommandIDs::closeAllDocuments, CommandIDs::closeAllDocuments,
CommandIDs::clearRecentFiles, CommandIDs::clearRecentFiles,
@ -622,18 +879,38 @@ void ProjucerApplication::getCommandInfo (CommandID commandID, ApplicationComman
switch (commandID) switch (commandID)
{ {
case CommandIDs::newProject: case CommandIDs::newProject:
result.setInfo ("New Project...", "Creates a new Jucer project", CommandCategories::general, 0); result.setInfo ("New Project...", "Creates a new JUCE project", CommandCategories::general, 0);
result.defaultKeypresses.add (KeyPress ('n', ModifierKeys::commandModifier, 0)); result.defaultKeypresses.add (KeyPress ('n', ModifierKeys::commandModifier, 0));
break; break;
case CommandIDs::newProjectFromClipboard:
result.setInfo ("New Project From Clipboard...", "Creates a new JUCE project from the clipboard contents", CommandCategories::general, 0);
result.defaultKeypresses.add (KeyPress ('n', ModifierKeys::commandModifier | ModifierKeys::shiftModifier, 0));
break;
case CommandIDs::launchDemoRunner:
#if JUCE_LINUX
if (makeProcess.isRunning())
{
result.setInfo ("Building Demo Runner...", "The Demo Runner project is currently building", CommandCategories::general, 0);
result.setActive (false);
}
else
#endif
{
result.setInfo ("Launch Demo Runner", "Launches the JUCE demo runner application, or the project if it can't be found", CommandCategories::general, 0);
result.setActive (findDemoRunnerExecutable() != File() || findDemoRunnerProject() != File());
}
break;
case CommandIDs::open: case CommandIDs::open:
result.setInfo ("Open...", "Opens a Jucer project", CommandCategories::general, 0); result.setInfo ("Open...", "Opens a JUCE project", CommandCategories::general, 0);
result.defaultKeypresses.add (KeyPress ('o', ModifierKeys::commandModifier, 0)); result.defaultKeypresses.add (KeyPress ('o', ModifierKeys::commandModifier, 0));
break; break;
case CommandIDs::showGlobalPathsWindow: case CommandIDs::showGlobalPathsWindow:
result.setInfo ("Global Search Paths...", result.setInfo ("Global Paths...",
"Shows the window to change the global search paths.", "Shows the window to change the stored global paths.",
CommandCategories::general, 0); CommandCategories::general, 0);
break; break;
@ -719,7 +996,9 @@ bool ProjucerApplication::perform (const InvocationInfo& info)
switch (info.commandID) switch (info.commandID)
{ {
case CommandIDs::newProject: createNewProject(); break; case CommandIDs::newProject: createNewProject(); break;
case CommandIDs::newProjectFromClipboard: createNewProjectFromClipboard(); break;
case CommandIDs::open: askUserToOpenFile(); break; case CommandIDs::open: askUserToOpenFile(); break;
case CommandIDs::launchDemoRunner: launchDemoRunner(); break;
case CommandIDs::saveAll: openDocumentManager.saveAll(); break; case CommandIDs::saveAll: openDocumentManager.saveAll(); break;
case CommandIDs::closeAllWindows: closeAllMainWindowsAndQuitIfNeeded(); break; case CommandIDs::closeAllWindows: closeAllMainWindowsAndQuitIfNeeded(); break;
case CommandIDs::closeAllDocuments: closeAllDocuments (true); break; case CommandIDs::closeAllDocuments: closeAllDocuments (true); break;
@ -743,11 +1022,30 @@ bool ProjucerApplication::perform (const InvocationInfo& info)
//============================================================================== //==============================================================================
void ProjucerApplication::createNewProject() void ProjucerApplication::createNewProject()
{ {
MainWindow* mw = mainWindowList.getOrCreateEmptyWindow(); auto* mw = mainWindowList.getOrCreateEmptyWindow();
mw->showNewProjectWizard(); mw->showStartPage();
mainWindowList.avoidSuperimposedWindows (mw); mainWindowList.avoidSuperimposedWindows (mw);
} }
void ProjucerApplication::createNewProjectFromClipboard()
{
auto tempFile = File::getSpecialLocation (File::SpecialLocationType::tempDirectory).getChildFile ("PIPs").getChildFile ("Clipboard")
.getChildFile ("PIPFile_" + String (std::abs (Random::getSystemRandom().nextInt())) + ".h");
if (tempFile.existsAsFile())
tempFile.deleteFile();
tempFile.create();
tempFile.appendText (SystemClipboard::getTextFromClipboard());
if (! findWindowAndOpenPIP (tempFile))
{
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, "Error", "Couldn't create project from clipboard contents.");
tempFile.deleteFile();
}
}
void ProjucerApplication::updateNewlyOpenedProject (Project& p) void ProjucerApplication::updateNewlyOpenedProject (Project& p)
{ {
LiveBuildProjectSettings::updateNewlyOpenedProject (p); LiveBuildProjectSettings::updateNewlyOpenedProject (p);
@ -850,10 +1148,10 @@ void ProjucerApplication::showPathsWindow()
if (pathsWindow != nullptr) if (pathsWindow != nullptr)
pathsWindow->toFront (true); pathsWindow->toFront (true);
else else
new FloatingToolWindow ("Global Search Paths", new FloatingToolWindow ("Global Paths",
"pathsWindowPos", "pathsWindowPos",
new GlobalSearchPathsWindowComponent(), pathsWindow, false, new GlobalPathsWindowComponent(), pathsWindow, false,
600, 500, 600, 500, 600, 500); 600, 550, 600, 550, 600, 550);
} }
void ProjucerApplication::showEditorColourSchemeWindow() void ProjucerApplication::showEditorColourSchemeWindow()
@ -980,6 +1278,14 @@ void ProjucerApplication::initCommandManager()
registerGUIEditorCommands(); registerGUIEditorCommands();
} }
void ProjucerApplication::deleteTemporaryFiles() const noexcept
{
auto tempDirectory = File::getSpecialLocation (File::SpecialLocationType::tempDirectory).getChildFile ("PIPs");
if (tempDirectory.exists())
tempDirectory.deleteRecursively();
}
void ProjucerApplication::selectEditorColourSchemeWithName (const String& schemeName) void ProjucerApplication::selectEditorColourSchemeWithName (const String& schemeName)
{ {
auto& appearanceSettings = getAppSettings().appearance; auto& appearanceSettings = getAppSettings().appearance;

View file

@ -88,6 +88,7 @@ public:
//============================================================================== //==============================================================================
void createNewProject(); void createNewProject();
void createNewProjectFromClipboard();
void updateNewlyOpenedProject (Project&); void updateNewlyOpenedProject (Project&);
void askUserToOpenFile(); void askUserToOpenFile();
bool openFile (const File&); bool openFile (const File&);
@ -166,6 +167,26 @@ private:
void handleAsyncUpdate() override; void handleAsyncUpdate() override;
void initCommandManager(); void initCommandManager();
void deleteTemporaryFiles() const noexcept;
void createExamplesPopupMenu (PopupMenu&) noexcept;
Array<File> getSortedExampleDirectories() const noexcept;
Array<File> getSortedExampleFilesInDirectory (const File&) const noexcept;
bool findWindowAndOpenPIP (const File&);
void findAndLaunchExample (int);
File findDemoRunnerExecutable() const noexcept;
File findDemoRunnerProject() const noexcept;
void launchDemoRunner();
int numExamples = 0;
ScopedPointer<AlertWindow> demoRunnerAlert;
#if JUCE_LINUX
ChildProcess makeProcess;
#endif
//============================================================================== //==============================================================================
void setColourScheme (int index, bool saveSetting); void setColourScheme (int index, bool saveSetting);

View file

@ -34,10 +34,13 @@ namespace CommandIDs
enum enum
{ {
newProject = 0x300000, newProject = 0x300000,
open = 0x300001, newProjectFromClipboard = 0x300001,
closeDocument = 0x300002, open = 0x300002,
saveDocument = 0x300003, closeDocument = 0x300003,
saveDocumentAs = 0x300004, saveDocument = 0x300004,
saveDocumentAs = 0x300005,
launchDemoRunner = 0x300006,
closeProject = 0x300010, closeProject = 0x300010,
saveProject = 0x300011, saveProject = 0x300011,

View file

@ -27,6 +27,7 @@
#include "jucer_Headers.h" #include "jucer_Headers.h"
#include "../Project/jucer_Module.h" #include "../Project/jucer_Module.h"
#include "../Utility/Helpers/jucer_TranslationHelpers.h" #include "../Utility/Helpers/jucer_TranslationHelpers.h"
#include "../Utility/PIPs/jucer_PIPGenerator.h"
#include "jucer_CommandLine.h" #include "jucer_CommandLine.h"
@ -34,8 +35,6 @@
//============================================================================== //==============================================================================
namespace namespace
{ {
static const char* getLineEnding() { return "\r\n"; }
struct CommandLineError struct CommandLineError
{ {
CommandLineError (const String& s) : message (s) {} CommandLineError (const String& s) : message (s) {}
@ -749,6 +748,31 @@ namespace
settingsFile.replaceWithText (settingsTree.toXmlString()); settingsFile.replaceWithText (settingsTree.toXmlString());
} }
static void createProjectFromPIP (const StringArray& args)
{
if (args.size() < 3)
throw CommandLineError ("Not enough arguments. Usage: --create-project-from-pip path/to/PIP path/to/output.");
auto pipFile = File::getCurrentWorkingDirectory().getChildFile (args[1].unquoted());
if (! pipFile.existsAsFile())
throw CommandLineError ("PIP file doesn't exist.");
auto outputDir = File::getCurrentWorkingDirectory().getChildFile (args[2].unquoted());
if (! outputDir.exists())
{
auto res = outputDir.createDirectory();
std::cout << "Creating directory " << outputDir.getFullPathName() << std::endl;
}
PIPGenerator generator (pipFile, outputDir);
if (! generator.createJucerFile())
throw CommandLineError ("Failed to create .jucer file in " + outputDir.getFullPathName()+ ".");
if (! generator.createMainCpp())
throw CommandLineError ("Failed to create Main.cpp.");
}
//============================================================================== //==============================================================================
static void showHelp() static void showHelp()
{ {
@ -812,8 +836,11 @@ namespace
<< " Creates a completed translations mapping file, that can be used to initialise a LocalisedStrings object. This allows you to localise the strings in your project" << std::endl << " Creates a completed translations mapping file, that can be used to initialise a LocalisedStrings object. This allows you to localise the strings in your project" << std::endl
<< std::endl << std::endl
<< " " << appName << " --set-global-search-path os identifier_to_set new_path" << std::endl << " " << appName << " --set-global-search-path os identifier_to_set new_path" << std::endl
<< " Sets the global search path for a specified os and identifier. The os should be either osx, windows or linux and the identifiers can be any of the following: " << " Sets the global path for a specified os and identifier. The os should be either osx, windows or linux and the identifiers can be any of the following: "
<< "defaultJuceModulePath, defaultUserModulePath, vst3path, aaxPath (not valid on linux), rtasPath (not valid on linux), androidSDKPath or androidNDKPath." << std::endl << "defaultJuceModulePath, defaultUserModulePath, vst3path, aaxPath (not valid on linux), rtasPath (not valid on linux), androidSDKPath or androidNDKPath." << std::endl
<< std::endl
<< " " << appName << " --create-project-from-pip path/to/PIP path/to/output" << std::endl
<< " Generates a JUCE project from a PIP file." << std::endl
<< std::endl; << std::endl;
} }
} }
@ -849,6 +876,7 @@ int performCommandLine (const String& commandLine)
if (matchArgument (command, "trans")) { scanFoldersForTranslationFiles (args); return 0; } if (matchArgument (command, "trans")) { scanFoldersForTranslationFiles (args); return 0; }
if (matchArgument (command, "trans-finish")) { createFinishedTranslationFile (args); return 0; } if (matchArgument (command, "trans-finish")) { createFinishedTranslationFile (args); return 0; }
if (matchArgument (command, "set-global-search-path")) { setGlobalPath (args); return 0; } if (matchArgument (command, "set-global-search-path")) { setGlobalPath (args); return 0; }
if (matchArgument (command, "create-project-from-pip")) { createProjectFromPIP (args); return 0; }
} }
catch (const CommandLineError& error) catch (const CommandLineError& error)
{ {

View file

@ -36,7 +36,7 @@
#include "Windows/jucer_AboutWindowComponent.h" #include "Windows/jucer_AboutWindowComponent.h"
#include "Windows/jucer_ApplicationUsageDataWindowComponent.h" #include "Windows/jucer_ApplicationUsageDataWindowComponent.h"
#include "Windows/jucer_EditorColourSchemeWindowComponent.h" #include "Windows/jucer_EditorColourSchemeWindowComponent.h"
#include "Windows/jucer_GlobalSearchPathsWindowComponent.h" #include "Windows/jucer_GlobalPathsWindowComponent.h"
#include "Windows/jucer_FloatingToolWindow.h" #include "Windows/jucer_FloatingToolWindow.h"
#include "../LiveBuildEngine/jucer_MessageIDs.h" #include "../LiveBuildEngine/jucer_MessageIDs.h"

View file

@ -29,7 +29,7 @@
#include "jucer_MainWindow.h" #include "jucer_MainWindow.h"
#include "../Wizards/jucer_NewProjectWizardClasses.h" #include "../Wizards/jucer_NewProjectWizardClasses.h"
#include "../Utility/UI/jucer_JucerTreeViewBase.h" #include "../Utility/UI/jucer_JucerTreeViewBase.h"
#include "../ProjectSaving/jucer_ProjectSaver.h"
//============================================================================== //==============================================================================
MainWindow::MainWindow() MainWindow::MainWindow()
@ -140,7 +140,7 @@ void MainWindow::closeButtonPressed()
ProjucerApplication::getApp().mainWindowList.closeWindow (this); ProjucerApplication::getApp().mainWindowList.closeWindow (this);
} }
bool MainWindow::closeProject (Project* project) bool MainWindow::closeProject (Project* project, bool askUserToSave)
{ {
jassert (project == currentProject && project != nullptr); jassert (project == currentProject && project != nullptr);
@ -156,12 +156,10 @@ bool MainWindow::closeProject (Project* project)
pcc->hideEditor(); pcc->hideEditor();
} }
if (! ProjucerApplication::getApp().openDocumentManager.closeAllDocumentsUsingProject (*project, true)) if (! ProjucerApplication::getApp().openDocumentManager.closeAllDocumentsUsingProject (*project, askUserToSave))
return false; return false;
auto r = project->saveIfNeededAndUserAgrees(); if (! askUserToSave || (project->saveIfNeededAndUserAgrees() == FileBasedDocument::savedOk))
if (r == FileBasedDocument::savedOk)
{ {
setProject (nullptr); setProject (nullptr);
return true; return true;
@ -175,6 +173,21 @@ bool MainWindow::closeCurrentProject()
return currentProject == nullptr || closeProject (currentProject.get()); return currentProject == nullptr || closeProject (currentProject.get());
} }
void MainWindow::moveProject (File newProjectFileToOpen)
{
auto openInIDE = currentProject->shouldOpenInIDEAfterSaving();
closeProject (currentProject, false);
openFile (newProjectFileToOpen);
if (currentProject != nullptr)
{
ProjucerApplication::getApp().getCommandManager().invokeDirectly (openInIDE ? CommandIDs::saveAndOpenInIDE
: CommandIDs::saveProject,
false);
}
}
void MainWindow::setProject (Project* newProject) void MainWindow::setProject (Project* newProject)
{ {
createProjectContentCompIfNeeded(); createProjectContentCompIfNeeded();
@ -186,6 +199,12 @@ void MainWindow::setProject (Project* newProject)
else else
projectNameValue.referTo (Value()); projectNameValue.referTo (Value());
if (newProject != nullptr)
{
if (auto* peer = getPeer())
peer->setRepresentedFile (newProject->getFile());
}
ProjucerApplication::getCommandManager().commandStatusChanged(); ProjucerApplication::getCommandManager().commandStatusChanged();
} }
@ -241,6 +260,142 @@ bool MainWindow::openFile (const File& file)
return false; return false;
} }
bool MainWindow::tryToOpenPIP (const File& pipFile)
{
PIPGenerator generator (pipFile);
if (! generator.hasValidPIP())
return false;
auto generatorResult = generator.createJucerFile();
if (generatorResult != Result::ok())
{
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
"PIP Error.",
generatorResult.getErrorMessage());
return false;
}
if (! generator.createMainCpp())
{
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
"PIP Error.",
"Failed to create Main.cpp.");
return false;
}
if (! ProjucerApplication::getApp().mainWindowList.openFile (generator.getJucerFile()))
return false;
openPIP (generator, pipFile.getFileName());
return true;
}
static bool isDivider (const String& line)
{
auto afterIndent = line.trim();
if (afterIndent.startsWith ("//") && afterIndent.length() > 20)
{
afterIndent = afterIndent.substring (2);
if (afterIndent.containsOnly ("=")
|| afterIndent.containsOnly ("/")
|| afterIndent.containsOnly ("-"))
{
return true;
}
}
return false;
}
static bool isEndOfCommentBlock (const String& line)
{
if (line.contains ("*/"))
return true;
return false;
}
static int getIndexOfCommentBlockStart (const StringArray& lines, int blockEndIndex)
{
for (int i = blockEndIndex; i >= 0; --i)
{
if (lines[i].contains ("/*"))
return i;
}
return 0;
}
static int findBestLineToScrollTo (StringArray lines, StringRef className)
{
for (auto line : lines)
{
if (line.contains ("struct " + className) || line.contains ("class " + className))
{
auto index = lines.indexOf (line);
if (isDivider (lines[index - 1]))
return index - 1;
if (isEndOfCommentBlock (lines[index - 1]))
{
auto blockStartIndex = getIndexOfCommentBlockStart (lines, index - 1);
if (blockStartIndex > 0 && isDivider (lines [blockStartIndex - 1]))
return blockStartIndex - 1;
return blockStartIndex;
}
return lines.indexOf (line);
}
}
return 0;
}
void MainWindow::openPIP (PIPGenerator& generator, StringRef fileName)
{
if (auto* window = ProjucerApplication::getApp().mainWindowList.getMainWindowForFile (generator.getJucerFile()))
{
if (auto* project = window->getProject())
{
project->setTemporaryDirectory (generator.getOutputDirectory());
ProjectSaver liveBuildSaver (*project, project->getFile());
liveBuildSaver.saveContentNeededForLiveBuild();
if (auto* pcc = window->getProjectContentComponent())
{
pcc->invokeDirectly (CommandIDs::toggleBuildEnabled, true);
pcc->invokeDirectly (CommandIDs::buildNow, true);
pcc->invokeDirectly (CommandIDs::toggleContinuousBuild, true);
auto fileToDisplay = project->getSourceFilesFolder().getChildFile (fileName);
if (fileToDisplay != File())
{
pcc->showEditorForFile (fileToDisplay, true);
if (auto* sourceCodeEditor = dynamic_cast <SourceCodeEditor*> (pcc->getEditorComponent()))
{
sourceCodeEditor->editor->scrollToLine (findBestLineToScrollTo (StringArray::fromLines (fileToDisplay.loadFileAsString()),
generator.getMainClassName()));
}
}
}
}
}
}
bool MainWindow::isInterestedInFileDrag (const StringArray& filenames) bool MainWindow::isInterestedInFileDrag (const StringArray& filenames)
{ {
for (auto& filename : filenames) for (auto& filename : filenames)
@ -256,7 +411,10 @@ void MainWindow::filesDropped (const StringArray& filenames, int /*mouseX*/, int
{ {
const File f (filename); const File f (filename);
if (canOpenFile (f) && openFile (f)) if (tryToOpenPIP (f))
continue;
if (! isPIPFile (f) && (canOpenFile (f) && openFile (f)))
break; break;
} }
} }
@ -326,9 +484,15 @@ void MainWindow::activeWindowStatusChanged()
{ {
if (auto* project = getProject()) if (auto* project = getProject())
{ {
auto oldTemporaryDirectory = project->getTemporaryDirectory();
auto projectFile = project->getFile(); auto projectFile = project->getFile();
setProject (nullptr); setProject (nullptr);
openFile (projectFile); openFile (projectFile);
if (oldTemporaryDirectory != File())
if (auto* newProject = getProject())
newProject->setTemporaryDirectory (oldTemporaryDirectory);
} }
} }
else else
@ -340,13 +504,16 @@ void MainWindow::activeWindowStatusChanged()
} }
} }
void MainWindow::showNewProjectWizard() void MainWindow::showStartPage()
{ {
jassert (currentProject == nullptr); jassert (currentProject == nullptr);
setContentOwned (createNewProjectWizardComponent(), true); setContentOwned (createNewProjectWizardComponent(), true);
centreWithSize (900, 630); centreWithSize (900, 630);
setVisible (true); setVisible (true);
addToDesktop(); addToDesktop();
getContentComponent()->grabKeyboardFocus(); getContentComponent()->grabKeyboardFocus();
} }
@ -453,7 +620,7 @@ bool MainWindowList::askAllWindowsToClose()
void MainWindowList::createWindowIfNoneAreOpen() void MainWindowList::createWindowIfNoneAreOpen()
{ {
if (windows.size() == 0) if (windows.size() == 0)
createNewMainWindow()->showNewProjectWizard(); createNewMainWindow()->showStartPage();
} }
void MainWindowList::closeWindow (MainWindow* w) void MainWindowList::closeWindow (MainWindow* w)
@ -542,7 +709,10 @@ bool MainWindowList::openFile (const File& file, bool openInBackground)
return ok; return ok;
} }
if (file.exists()) if (getFrontmostWindow()->tryToOpenPIP (file))
return true;
if (! isPIPFile (file) && file.exists())
return getFrontmostWindow()->openFile (file); return getFrontmostWindow()->openFile (file);
return false; return false;
@ -599,6 +769,23 @@ MainWindow* MainWindowList::getOrCreateEmptyWindow()
return createNewMainWindow(); return createNewMainWindow();
} }
MainWindow* MainWindowList::getMainWindowForFile (const File& file)
{
if (windows.size() > 0)
{
for (auto* window : windows)
{
if (auto* project = window->getProject())
{
if (project->getFile() == file)
return window;
}
}
}
return nullptr;
}
void MainWindowList::avoidSuperimposedWindows (MainWindow* const mw) void MainWindowList::avoidSuperimposedWindows (MainWindow* const mw)
{ {
for (int i = windows.size(); --i >= 0;) for (int i = windows.size(); --i >= 0;)
@ -633,7 +820,8 @@ void MainWindowList::saveCurrentlyOpenProjectList()
{ {
if (auto* mw = dynamic_cast<MainWindow*> (desktop.getComponent(i))) if (auto* mw = dynamic_cast<MainWindow*> (desktop.getComponent(i)))
if (auto* p = mw->getProject()) if (auto* p = mw->getProject())
projects.add (p->getFile()); if (! p->isTemporaryProject())
projects.add (p->getFile());
} }
getAppSettings().setLastProjects (projects); getAppSettings().setLastProjects (projects);

View file

@ -27,6 +27,7 @@
#pragma once #pragma once
#include "../Project/UI/jucer_ProjectContentComponent.h" #include "../Project/UI/jucer_ProjectContentComponent.h"
#include "../Utility/PIPs/jucer_PIPGenerator.h"
//============================================================================== //==============================================================================
/** /**
@ -51,13 +52,15 @@ public:
bool openFile (const File& file); bool openFile (const File& file);
void setProject (Project* newProject); void setProject (Project* newProject);
Project* getProject() const { return currentProject.get(); } Project* getProject() const { return currentProject.get(); }
bool tryToOpenPIP (const File& f);
void makeVisible(); void makeVisible();
void restoreWindowPosition(); void restoreWindowPosition();
bool closeProject (Project* project); bool closeProject (Project* project, bool askToSave = true);
bool closeCurrentProject(); bool closeCurrentProject();
void moveProject (File newProjectFile);
void showNewProjectWizard(); void showStartPage();
bool isInterestedInFileDrag (const StringArray& files) override; bool isInterestedInFileDrag (const StringArray& files) override;
void filesDropped (const StringArray& filenames, int mouseX, int mouseY) override; void filesDropped (const StringArray& filenames, int mouseX, int mouseY) override;
@ -82,6 +85,8 @@ private:
void createProjectContentCompIfNeeded(); void createProjectContentCompIfNeeded();
void setTitleBarIcon(); void setTitleBarIcon();
void openPIP (PIPGenerator&, StringRef fileName);
void valueChanged (Value&) override; void valueChanged (Value&) override;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainWindow) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainWindow)
@ -106,6 +111,7 @@ public:
MainWindow* createNewMainWindow(); MainWindow* createNewMainWindow();
MainWindow* getFrontmostWindow (bool createIfNotFound = true); MainWindow* getFrontmostWindow (bool createIfNotFound = true);
MainWindow* getOrCreateEmptyWindow(); MainWindow* getOrCreateEmptyWindow();
MainWindow* getMainWindowForFile (const File&);
Project* getFrontmostProject(); Project* getFrontmostProject();

View file

@ -684,6 +684,11 @@ void CompileEngineChildProcess::handleAppQuit()
runningAppProcess.reset(); runningAppProcess.reset();
} }
bool CompileEngineChildProcess::isAppRunning() const noexcept
{
return runningAppProcess != nullptr && runningAppProcess->isRunningApp;
}
//============================================================================== //==============================================================================
struct CompileEngineChildProcess::Editor : private CodeDocument::Listener, struct CompileEngineChildProcess::Editor : private CodeDocument::Listener,
private Timer private Timer

View file

@ -52,6 +52,7 @@ public:
void launchApp(); void launchApp();
bool canKillApp() const; bool canKillApp() const;
void killApp(); void killApp();
bool isAppRunning() const noexcept;
const ClassDatabase::ClassList& getComponentList() const { return lastComponentList; } const ClassDatabase::ClassList& getComponentList() const { return lastComponentList; }

View file

@ -192,8 +192,8 @@ private:
globalPathValue.referTo (modules.getShouldUseGlobalPathValue (moduleID)); globalPathValue.referTo (modules.getShouldUseGlobalPathValue (moduleID));
auto menuItemString = (TargetOS::getThisOS() == TargetOS::osx ? "\"Projucer->Global Search Paths...\"" auto menuItemString = (TargetOS::getThisOS() == TargetOS::osx ? "\"Projucer->Global Paths...\""
: "\"File->Global Search Paths...\""); : "\"File->Global Paths...\"");
props.add (new BooleanPropertyComponent (globalPathValue, props.add (new BooleanPropertyComponent (globalPathValue,
"Use global path", "Use global path for this module"), "Use global path", "Use global path for this module"),

View file

@ -0,0 +1,372 @@
/*
==============================================================================
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_HeaderComponent.h"
#include "../../ProjectSaving/jucer_ProjectExporter.h"
#include "../../Project/UI/jucer_ProjectContentComponent.h"
#include "../../LiveBuildEngine/jucer_MessageIDs.h"
#include "../../LiveBuildEngine/jucer_SourceCodeRange.h"
#include "../../LiveBuildEngine/jucer_ClassDatabase.h"
#include "../../LiveBuildEngine/jucer_DiagnosticMessage.h"
#include "../../LiveBuildEngine/jucer_CompileEngineClient.h"
//======================================================================
HeaderComponent::HeaderComponent()
{
addAndMakeVisible (configLabel);
addAndMakeVisible (exporterBox);
exporterBox.onChange = [this] { updateExporterButton(); };
addAndMakeVisible (juceIcon = new ImageComponent ("icon"));
juceIcon->setImage (ImageCache::getFromMemory (BinaryData::juce_icon_png, BinaryData::juce_icon_pngSize),
RectanglePlacement::centred);
projectNameLabel.setText ({}, dontSendNotification);
addAndMakeVisible (projectNameLabel);
initialiseButtons();
}
HeaderComponent::~HeaderComponent()
{
if (userSettingsWindow != nullptr)
userSettingsWindow->dismiss();
if (childProcess != nullptr)
{
childProcess->activityList.removeChangeListener(this);
childProcess->errorList.removeChangeListener (this);
}
}
//======================================================================
void HeaderComponent::resized()
{
auto bounds = getLocalBounds();
configLabel.setFont ({ bounds.getHeight() / 3.0f });
//======================================================================
{
auto headerBounds = bounds.removeFromLeft (tabsWidth);
const int buttonSize = 25;
auto buttonBounds = headerBounds.removeFromRight (buttonSize);
projectSettingsButton->setBounds (buttonBounds.removeFromBottom (buttonSize).reduced (2));
juceIcon->setBounds (headerBounds.removeFromLeft (headerBounds.getHeight()).reduced (2));
headerBounds.removeFromRight (5);
projectNameLabel.setBounds (headerBounds);
}
//======================================================================
auto exporterWidth = jmin (400, bounds.getWidth() / 2);
Rectangle<int> exporterBounds (0, 0, exporterWidth, bounds.getHeight());
exporterBounds.setCentre (bounds.getCentre());
runAppButton->setBounds (exporterBounds.removeFromRight (exporterBounds.getHeight()).reduced (2));
saveAndOpenInIDEButton->setBounds (exporterBounds.removeFromRight (exporterBounds.getHeight()).reduced (2));
exporterBounds.removeFromRight (5);
exporterBox.setBounds (exporterBounds.removeFromBottom (roundToInt (exporterBounds.getHeight() / 1.8f)));
configLabel.setBounds (exporterBounds);
bounds.removeFromRight (5);
userSettingsButton->setBounds (bounds.removeFromRight (bounds.getHeight()).reduced (2));
}
void HeaderComponent::paint (Graphics& g)
{
g.fillAll (findColour (backgroundColourId));
if (isBuilding)
getLookAndFeel().drawSpinningWaitAnimation (g, findColour (treeIconColourId),
runAppButton->getX(), runAppButton->getY(),
runAppButton->getWidth(), runAppButton->getHeight());
}
//======================================================================
void HeaderComponent::setCurrentProject (Project* p) noexcept
{
project = p;
exportersTree = project->getExporters();
exportersTree.addListener (this);
updateExporters();
project->addChangeListener (this);
updateName();
isBuilding = false;
stopTimer();
repaint();
childProcess = ProjucerApplication::getApp().childProcessCache->getExisting (*project);
if (childProcess != nullptr)
{
childProcess->activityList.addChangeListener (this);
childProcess->errorList.addChangeListener (this);
}
if (childProcess != nullptr)
{
runAppButton->setTooltip ({});
runAppButton->setEnabled (true);
}
else
{
runAppButton->setTooltip ("Enable live-build engine to launch application");
runAppButton->setEnabled (false);
}
}
//======================================================================
void HeaderComponent::updateExporters() noexcept
{
auto selectedName = getSelectedExporterName();
exporterBox.clear();
auto preferredExporterIndex = -1;
int i = 0;
for (Project::ExporterIterator exporter (*project); exporter.next(); ++i)
{
exporterBox.addItem (exporter->getName(), i + 1);
if (selectedName == exporter->getName())
exporterBox.setSelectedId (i + 1);
if (exporter->canLaunchProject() && preferredExporterIndex == -1)
preferredExporterIndex = i;
}
if (exporterBox.getSelectedItemIndex() == -1)
exporterBox.setSelectedItemIndex (preferredExporterIndex != -1 ? preferredExporterIndex
: 0);
updateExporterButton();
}
String HeaderComponent::getSelectedExporterName() const noexcept
{
return exporterBox.getItemText (exporterBox.getSelectedItemIndex());
}
bool HeaderComponent::canCurrentExporterLaunchProject() const noexcept
{
for (Project::ExporterIterator exporter (*project); exporter.next();)
if (exporter->getName() == getSelectedExporterName() && exporter->canLaunchProject())
return true;
return false;
}
//======================================================================
int HeaderComponent::getUserButtonWidth() const noexcept
{
return userSettingsButton->getWidth();
}
void HeaderComponent::sidebarTabsWidthChanged (int newWidth) noexcept
{
tabsWidth = newWidth;
resized();
}
//======================================================================
void HeaderComponent::showUserSettings() noexcept
{
#if JUCER_ENABLE_GPL_MODE
auto settingsPopupHeight = 40;
auto settingsPopupWidth = 200;
#else
auto settingsPopupHeight = 150;
auto settingsPopupWidth = 250;
#endif
auto* content = new UserSettingsPopup (false);
content->setSize (settingsPopupWidth, settingsPopupHeight);
userSettingsWindow = &CallOutBox::launchAsynchronously (content, userSettingsButton->getScreenBounds(), nullptr);
}
//==========================================================================
void HeaderComponent::lookAndFeelChanged()
{
if (userSettingsWindow != nullptr)
userSettingsWindow->sendLookAndFeelChange();
}
void HeaderComponent::changeListenerCallback (ChangeBroadcaster* source)
{
if (source == project)
{
updateName();
updateExporters();
}
else if (childProcess != nullptr)
{
if (childProcess->activityList.getNumActivities() > 0)
buildPing();
else
buildFinished (childProcess->errorList.getNumErrors() == 0);
}
}
void HeaderComponent::timerCallback()
{
repaint();
}
//======================================================================
void HeaderComponent::initialiseButtons() noexcept
{
auto& icons = getIcons();
addAndMakeVisible (projectSettingsButton = new IconButton ("Project Settings", &icons.settings));
projectSettingsButton->onClick = [this]
{
if (auto* pcc = findParentComponentOfClass<ProjectContentComponent>())
pcc->showProjectSettings();
};
addAndMakeVisible (saveAndOpenInIDEButton = new IconButton ("Save and Open in IDE", nullptr));
saveAndOpenInIDEButton->isIDEButton = true;
saveAndOpenInIDEButton->onClick = [this]
{
if (auto* pcc = findParentComponentOfClass<ProjectContentComponent>())
pcc->openInSelectedIDE (true);
};
addAndMakeVisible (userSettingsButton = new IconButton ("User Settings", &icons.user));
userSettingsButton->isUserButton = true;
userSettingsButton->onClick = [this]
{
if (auto* pcc = findParentComponentOfClass<ProjectContentComponent>())
showUserSettings();
};
addAndMakeVisible (runAppButton = new IconButton ("Run Application", &icons.play));
runAppButton->onClick = [this]
{
if (childProcess != nullptr)
childProcess->launchApp();
};
updateExporterButton();
updateUserAvatar();
}
void HeaderComponent::updateName() noexcept
{
projectNameLabel.setText (project->getDocumentTitle(), dontSendNotification);
}
void HeaderComponent::updateExporterButton() noexcept
{
auto currentExporterName = getSelectedExporterName();
for (auto info : ProjectExporter::getExporterTypes())
{
if (currentExporterName.contains (info.name))
{
saveAndOpenInIDEButton->iconImage = info.getIcon();
saveAndOpenInIDEButton->repaint();
saveAndOpenInIDEButton->setEnabled (canCurrentExporterLaunchProject());
}
}
}
void HeaderComponent::updateUserAvatar() noexcept
{
if (auto* controller = ProjucerApplication::getApp().licenseController.get())
{
auto state = controller->getState();
userSettingsButton->iconImage = state.avatar;
userSettingsButton->repaint();
}
}
//======================================================================
void HeaderComponent::buildPing()
{
if (! isTimerRunning())
{
isBuilding = true;
runAppButton->setEnabled (false);
runAppButton->setTooltip ("Building...");
startTimer (50);
}
}
void HeaderComponent::buildFinished (bool success)
{
stopTimer();
isBuilding = false;
repaint();
setRunAppButtonState (success);
}
void HeaderComponent::setRunAppButtonState (bool buildWasSuccessful)
{
bool shouldEnableButton = false;
if (buildWasSuccessful)
{
if (childProcess != nullptr)
{
if (childProcess->isAppRunning() || (! childProcess->isAppRunning() && childProcess->canLaunchApp()))
{
runAppButton->setTooltip ("Launch application");
shouldEnableButton = true;
}
else
{
runAppButton->setTooltip ("Application can't be launched");
}
}
else
{
runAppButton->setTooltip ("Enable live-build engine to launch application");
}
}
else
{
runAppButton->setTooltip ("Error building application");
}
runAppButton->setEnabled (shouldEnableButton);
}

View file

@ -26,205 +26,48 @@
#pragma once #pragma once
#include "../../Application/jucer_Headers.h"
#include "../../Utility/UI/jucer_IconButton.h" #include "../../Utility/UI/jucer_IconButton.h"
#include "../../Utility/UI/jucer_UserSettingsPopup.h" #include "../../Utility/UI/jucer_UserSettingsPopup.h"
class Project;
//============================================================================== //==============================================================================
class HeaderComponent : public Component, class HeaderComponent : public Component,
private ValueTree::Listener, private ValueTree::Listener,
private ChangeListener private ChangeListener,
private Timer
{ {
public: public:
HeaderComponent() HeaderComponent();
: configLabel ("Config Label", "Selected exporter") ~HeaderComponent();
{
addAndMakeVisible (configLabel);
addAndMakeVisible (exporterBox);
exporterBox.onChange = [this] { updateExporterButton(); };
addAndMakeVisible (juceIcon = new ImageComponent ("icon"));
juceIcon->setImage (ImageCache::getFromMemory (BinaryData::juce_icon_png, BinaryData::juce_icon_pngSize),
RectanglePlacement::centred);
projectNameLabel.setText (String(), dontSendNotification);
addAndMakeVisible (projectNameLabel);
initialiseButtons();
}
~HeaderComponent()
{
if (userSettingsWindow != nullptr)
userSettingsWindow->dismiss();
}
void resized() override
{
auto bounds = getLocalBounds();
configLabel.setFont ({ bounds.getHeight() / 3.0f });
//======================================================================
auto projectHeaderBounds = bounds.removeFromLeft (tabsWidth);
juceIcon->setBounds (projectHeaderBounds.removeFromLeft (projectHeaderBounds.getHeight()).reduced (5, 5));
projectSettingsButton->setBounds (projectHeaderBounds.removeFromRight (projectHeaderBounds.getHeight()).reduced (2, 2));
projectNameLabel.setBounds (projectHeaderBounds);
//======================================================================
bounds.removeFromLeft (33);
continuousRebuildButton->setBounds (bounds.removeFromLeft (bounds.getHeight()).reduced (2, 2));
bounds.removeFromLeft (5);
buildNowButton->setBounds (bounds.removeFromLeft (bounds.getHeight()).reduced (2, 2));
bounds.removeFromRight (5);
userSettingsButton->setBounds (bounds.removeFromRight (bounds.getHeight()).reduced (2, 2));
auto exporterWidth = jmax (250, bounds.getWidth() / 2);
auto spacing = bounds.getWidth() - exporterWidth;
auto leftSpacing = jmax (20, spacing / 3);
auto rightSpacing = jmax (40, 2 * (spacing / 3));
bounds.removeFromLeft (leftSpacing);
bounds.removeFromRight (rightSpacing);
saveAndOpenInIDEButton->setBounds (bounds.removeFromRight (bounds.getHeight()).reduced (2, 2));
bounds.removeFromRight (5);
exporterSettingsButton->setBounds (bounds.removeFromRight (bounds.getHeight()).reduced (2, 2));
bounds.removeFromRight (10);
exporterBox.setBounds (bounds.removeFromBottom (roundToInt (bounds.getHeight() / 1.8f)));
configLabel.setBounds (bounds);
}
void paint (Graphics& g) override
{
g.fillAll (findColour (backgroundColourId));
}
void setCurrentProject (Project* p)
{
project = p;
exportersTree = project->getExporters();
exportersTree.addListener (this);
updateExporters();
project->addChangeListener (this);
updateName();
if (auto* pcc = findParentComponentOfClass<ProjectContentComponent>())
updateBuildButtons (pcc->isBuildEnabled(), pcc->isContinuousRebuildEnabled());
}
void updateExporters()
{
auto selectedName = getSelectedExporterName();
exporterBox.clear();
auto preferredExporterIndex = -1;
int i = 0;
for (Project::ExporterIterator exporter (*project); exporter.next(); ++i)
{
exporterBox.addItem (exporter->getName(), i + 1);
if (selectedName == exporter->getName())
exporterBox.setSelectedId (i + 1);
if (exporter->canLaunchProject() && preferredExporterIndex == -1)
preferredExporterIndex = i;
}
if (exporterBox.getSelectedItemIndex() == -1)
exporterBox.setSelectedItemIndex (preferredExporterIndex != -1 ? preferredExporterIndex
: 0);
updateExporterButton();
}
String getSelectedExporterName()
{
return exporterBox.getItemText (exporterBox.getSelectedItemIndex());
}
bool canCurrentExporterLaunchProject()
{
for (Project::ExporterIterator exporter (*project); exporter.next();)
if (exporter->getName() == getSelectedExporterName() && exporter->canLaunchProject())
return true;
return false;
}
int getUserButtonWidth() { return userSettingsButton->getWidth(); }
void sidebarTabsWidthChanged (int newWidth)
{
tabsWidth = newWidth;
resized();
}
void showUserSettings()
{
#if JUCER_ENABLE_GPL_MODE
auto settingsPopupHeight = 40;
auto settingsPopupWidth = 200;
#else
auto settingsPopupHeight = 150;
auto settingsPopupWidth = 250;
#endif
auto* content = new UserSettingsPopup (false);
content->setSize (settingsPopupWidth, settingsPopupHeight);
userSettingsWindow = &CallOutBox::launchAsynchronously (content, userSettingsButton->getScreenBounds(), nullptr);
}
void updateBuildButtons (bool isBuildEnabled, bool isContinuousRebuildEnabled)
{
buildNowButton->setEnabled (isBuildEnabled && ! isContinuousRebuildEnabled);
continuousRebuildButton->setEnabled (isBuildEnabled);
continuousRebuildButton->icon = Icon (isContinuousRebuildEnabled ? &getIcons().continuousBuildStop : &getIcons().continuousBuildStart,
Colours::transparentBlack);
repaint();
}
void lookAndFeelChanged() override
{
if (userSettingsWindow != nullptr)
userSettingsWindow->sendLookAndFeelChange();
}
private:
Project* project = nullptr;
ValueTree exportersTree;
Label configLabel, projectNameLabel;
ComboBox exporterBox;
ScopedPointer<ImageComponent> juceIcon;
ScopedPointer<IconButton> projectSettingsButton, continuousRebuildButton, buildNowButton,
exporterSettingsButton, saveAndOpenInIDEButton, userSettingsButton;
SafePointer<CallOutBox> userSettingsWindow;
int tabsWidth = 200;
//========================================================================== //==========================================================================
void changeListenerCallback (ChangeBroadcaster* source) override void resized() override;
{ void paint (Graphics&) override;
if (source == project)
{
updateName();
updateExporters();
}
}
//==========================================================================
void setCurrentProject (Project*) noexcept;
//==========================================================================
void updateExporters() noexcept;
String getSelectedExporterName() const noexcept;
bool canCurrentExporterLaunchProject() const noexcept;
//==========================================================================
int getUserButtonWidth() const noexcept;
void sidebarTabsWidthChanged (int newWidth) noexcept;
//==========================================================================
void showUserSettings() noexcept;
private:
//==========================================================================
void lookAndFeelChanged() override;
void changeListenerCallback (ChangeBroadcaster* source) override;
void timerCallback() override;
//==========================================================================
void valueTreePropertyChanged (ValueTree&, const Identifier&) override {} void valueTreePropertyChanged (ValueTree&, const Identifier&) override {}
void valueTreeParentChanged (ValueTree&) override {} void valueTreeParentChanged (ValueTree&) override {}
@ -232,94 +75,41 @@ private:
void valueTreeChildRemoved (ValueTree& parentTree, ValueTree&, int) override { updateIfNeeded (parentTree); } void valueTreeChildRemoved (ValueTree& parentTree, ValueTree&, int) override { updateIfNeeded (parentTree); }
void valueTreeChildOrderChanged (ValueTree& parentTree, int, int) override { updateIfNeeded (parentTree); } void valueTreeChildOrderChanged (ValueTree& parentTree, int, int) override { updateIfNeeded (parentTree); }
void initialiseButtons() void updateIfNeeded (ValueTree tree) noexcept
{
auto& icons = getIcons();
addAndMakeVisible (projectSettingsButton = new IconButton ("Project Settings", &icons.settings));
projectSettingsButton->onClick = [this]
{
if (auto* pcc = findParentComponentOfClass<ProjectContentComponent>())
pcc->showProjectSettings();
};
addAndMakeVisible (continuousRebuildButton = new IconButton ("Continuous Rebuild", &icons.continuousBuildStart));
continuousRebuildButton->onClick = [this]
{
if (auto* pcc = findParentComponentOfClass<ProjectContentComponent>())
pcc->setContinuousRebuildEnabled (! pcc->isContinuousRebuildEnabled());
};
addAndMakeVisible (buildNowButton = new IconButton ("Build Now", &icons.buildNow));
buildNowButton->onClick = [this]
{
if (auto* pcc = findParentComponentOfClass<ProjectContentComponent>())
pcc->rebuildNow();
};
addAndMakeVisible (exporterSettingsButton = new IconButton ("Exporter Settings", &icons.edit));
exporterSettingsButton->onClick = [this]
{
if (auto* pcc = findParentComponentOfClass<ProjectContentComponent>())
pcc->showExporterSettings (getSelectedExporterName());
};
addAndMakeVisible (saveAndOpenInIDEButton = new IconButton ("Save and Open in IDE", nullptr));
saveAndOpenInIDEButton->isIDEButton = true;
saveAndOpenInIDEButton->onClick = [this]
{
if (auto* pcc = findParentComponentOfClass<ProjectContentComponent>())
pcc->openInSelectedIDE (true);
};
addAndMakeVisible (userSettingsButton = new IconButton ("User Settings", &icons.user));
userSettingsButton->isUserButton = true;
userSettingsButton->onClick = [this]
{
if (auto* pcc = findParentComponentOfClass<ProjectContentComponent>())
showUserSettings();
};
updateExporterButton();
updateUserAvatar();
}
void updateIfNeeded (ValueTree tree)
{ {
if (tree == exportersTree) if (tree == exportersTree)
updateExporters(); updateExporters();
} }
void updateName() //==========================================================================
{ void initialiseButtons() noexcept;
projectNameLabel.setText (project->getDocumentTitle(), dontSendNotification);
}
void updateExporterButton() void updateName() noexcept;
{ void updateExporterButton() noexcept;
auto currentExporterName = getSelectedExporterName(); void updateUserAvatar() noexcept;
for (auto info : ProjectExporter::getExporterTypes()) //==========================================================================
{ void buildPing();
if (currentExporterName.contains (info.name)) void buildFinished (bool);
{ void setRunAppButtonState (bool);
saveAndOpenInIDEButton->iconImage = info.getIcon();
saveAndOpenInIDEButton->repaint();
saveAndOpenInIDEButton->setEnabled (canCurrentExporterLaunchProject());
}
}
}
void updateUserAvatar() //==========================================================================
{ int tabsWidth = 200;
if (auto* controller = ProjucerApplication::getApp().licenseController.get()) bool isBuilding = false;
{
auto state = controller->getState();
userSettingsButton->iconImage = state.avatar; Project* project = nullptr;
userSettingsButton->repaint(); ValueTree exportersTree;
}
} ComboBox exporterBox;
Label configLabel { "Config Label", "Selected exporter" },
projectNameLabel;
ScopedPointer<ImageComponent> juceIcon;
ScopedPointer<IconButton> projectSettingsButton, saveAndOpenInIDEButton, userSettingsButton, runAppButton;
SafePointer<CallOutBox> userSettingsWindow;
ReferenceCountedObjectPtr<CompileEngineChildProcess> childProcess;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (HeaderComponent) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (HeaderComponent)
}; };

View file

@ -478,7 +478,9 @@ void ProjectContentComponent::saveDocument()
showSaveWarning (currentDocument); showSaveWarning (currentDocument);
} }
else else
{
saveProject(); saveProject();
}
} }
void ProjectContentComponent::saveAs() void ProjectContentComponent::saveAs()
@ -521,11 +523,13 @@ bool ProjectContentComponent::goToCounterpart()
return false; return false;
} }
bool ProjectContentComponent::saveProject (bool shouldWait) bool ProjectContentComponent::saveProject (bool shouldWait, bool openInIDE)
{ {
if (project != nullptr) if (project != nullptr)
{ {
const ScopedValueSetter<bool> valueSetter (project->shouldWaitAfterSaving, shouldWait, false); const ScopedValueSetter<bool> valueSetter (project->shouldWaitAfterSaving, shouldWait, false);
project->setOpenInIDEAfterSaving (openInIDE);
return (project->save (true, true) == FileBasedDocument::savedOk); return (project->save (true, true) == FileBasedDocument::savedOk);
} }
@ -637,11 +641,16 @@ void ProjectContentComponent::openInSelectedIDE (bool saveFirst)
{ {
if (exporter->canLaunchProject() && exporter->getName() == selectedIDE) if (exporter->canLaunchProject() && exporter->getName() == selectedIDE)
{ {
if (saveFirst && ! saveProject (exporter->isXcode())) auto tempProject = project->isTemporaryProject(); // store this before saving as it will always be false after
if (saveFirst && ! saveProject (exporter->isXcode(), true))
return;
if (tempProject)
return; return;
exporter->launchProject(); exporter->launchProject();
break; return;
} }
} }
} }
@ -1155,9 +1164,6 @@ void ProjectContentComponent::setBuildEnabled (bool isEnabled, bool displayError
LiveBuildProjectSettings::setBuildDisabled (*project, ! isEnabled); LiveBuildProjectSettings::setBuildDisabled (*project, ! isEnabled);
killChildProcess(); killChildProcess();
refreshTabsIfBuildStatusChanged(); refreshTabsIfBuildStatusChanged();
if (auto* h = dynamic_cast<HeaderComponent*> (header.get()))
h->updateBuildButtons (isEnabled, isContinuousRebuildEnabled());
} }
} }
@ -1300,11 +1306,7 @@ void ProjectContentComponent::setContinuousRebuildEnabled (bool b)
{ {
childProcess->setContinuousRebuild (b); childProcess->setContinuousRebuild (b);
if (auto* h = dynamic_cast<HeaderComponent*> (header.get()))
h->updateBuildButtons (isBuildEnabled(), b);
getAppSettings().getGlobalProperties().setValue ("continuousRebuild", b); getAppSettings().getGlobalProperties().setValue ("continuousRebuild", b);
ProjucerApplication::getCommandManager().commandStatusChanged(); ProjucerApplication::getCommandManager().commandStatusChanged();
} }
} }

View file

@ -75,7 +75,7 @@ public:
bool canGoToCounterpart() const; bool canGoToCounterpart() const;
bool goToCounterpart(); bool goToCounterpart();
bool saveProject (bool shouldWait = false); bool saveProject (bool shouldWait = false, bool openInIDE = false);
void closeProject(); void closeProject();
void openInSelectedIDE (bool saveFirst); void openInSelectedIDE (bool saveFirst);
void showNewExporterMenu(); void showNewExporterMenu();

View file

@ -394,6 +394,13 @@ static void registerRecentFile (const File& file)
getAppSettings().flush(); getAppSettings().flush();
} }
static void forgetRecentFile (const File& file)
{
RecentlyOpenedFilesList::forgetRecentFileNatively (file);
getAppSettings().recentFiles.removeFile (file);
getAppSettings().flush();
}
//============================================================================== //==============================================================================
Result Project::loadDocument (const File& file) Result Project::loadDocument (const File& file)
{ {
@ -408,6 +415,7 @@ Result Project::loadDocument (const File& file)
return Result::fail ("The document contains errors and couldn't be parsed!"); return Result::fail ("The document contains errors and couldn't be parsed!");
registerRecentFile (file); registerRecentFile (file);
enabledModulesList.reset(); enabledModulesList.reset();
projectRoot = newTree; projectRoot = newTree;
@ -437,9 +445,15 @@ Result Project::saveProject (const File& file, bool isCommandLineApp)
if (isSaving) if (isSaving)
return Result::ok(); return Result::ok();
if (isTemporaryProject())
{
askUserWhereToSaveProject();
return Result::ok();
}
updateProjectSettings(); updateProjectSettings();
if (! isCommandLineApp) if (! isCommandLineApp && ! isTemporaryProject())
registerRecentFile (file); registerRecentFile (file);
const ScopedValueSetter<bool> vs (isSaving, true, false); const ScopedValueSetter<bool> vs (isSaving, true, false);
@ -454,17 +468,55 @@ Result Project::saveResourcesOnly (const File& file)
return saver.saveResourcesOnly(); return saver.saveResourcesOnly();
} }
//==============================================================================
void Project::setTemporaryDirectory (const File& dir) noexcept
{
tempDirectory = dir;
// remove this file from the recent documents list as it is a temporary project
forgetRecentFile (getFile());
}
void Project::askUserWhereToSaveProject()
{
FileChooser fc ("Save Project");
fc.browseForDirectory();
if (fc.getResult().exists())
moveTemporaryDirectory (fc.getResult());
}
void Project::moveTemporaryDirectory (const File& newParentDirectory)
{
auto newDirectory = newParentDirectory.getChildFile (tempDirectory.getFileName());
auto oldJucerFileName = getFile().getFileName();
tempDirectory.copyDirectoryTo (newDirectory);
tempDirectory.deleteRecursively();
tempDirectory = File();
// reload project from new location
if (auto* window = ProjucerApplication::getApp().mainWindowList.getMainWindowForFile (getFile()))
window->moveProject (newDirectory.getChildFile (oldJucerFileName));
}
//============================================================================== //==============================================================================
void Project::valueTreePropertyChanged (ValueTree& tree, const Identifier& property) void Project::valueTreePropertyChanged (ValueTree& tree, const Identifier& property)
{ {
if (tree.getRoot() == tree) if (tree.getRoot() == tree)
{ {
if (property == Ids::projectType) if (property == Ids::projectType)
{
sendChangeMessage(); sendChangeMessage();
}
else if (property == Ids::name) else if (property == Ids::name)
{
setTitle (projectRoot [Ids::name]); setTitle (projectRoot [Ids::name]);
}
else if (property == Ids::defines) else if (property == Ids::defines)
{
parsedPreprocessorDefs = parsePreprocessorDefs (preprocessorDefsValue.get()); parsedPreprocessorDefs = parsePreprocessorDefs (preprocessorDefsValue.get());
}
changed(); changed();
} }

View file

@ -31,6 +31,7 @@
class ProjectExporter; class ProjectExporter;
class LibraryModule; class LibraryModule;
class EnabledModuleList; class EnabledModuleList;
class ProjectContentComponent;
//============================================================================== //==============================================================================
class Project : public FileBasedDocument, class Project : public FileBasedDocument,
@ -331,10 +332,18 @@ public:
String getUniqueTargetFolderSuffixForExporter (const String& exporterName, const String& baseTargetFolder); String getUniqueTargetFolderSuffixForExporter (const String& exporterName, const String& baseTargetFolder);
//============================================================================== //==============================================================================
bool isCurrentlySaving() const noexcept { return isSaving; } bool isCurrentlySaving() const noexcept { return isSaving; }
bool shouldWaitAfterSaving = false; bool shouldWaitAfterSaving = false;
String specifiedExporterToSave = {}; String specifiedExporterToSave = {};
//==============================================================================
bool isTemporaryProject() const noexcept { return tempDirectory != File(); }
File getTemporaryDirectory() const noexcept { return tempDirectory; }
void setTemporaryDirectory (const File&) noexcept;
void setOpenInIDEAfterSaving (bool open) noexcept { openInIDEAfterSaving = open; }
bool shouldOpenInIDEAfterSaving() const noexcept { return openInIDEAfterSaving; }
private: private:
ValueTree projectRoot { Ids::JUCERPROJECT }; ValueTree projectRoot { Ids::JUCERPROJECT };
@ -349,6 +358,16 @@ private:
pluginAUMainTypeValue, pluginRTASCategoryValue, pluginRTASBypassDisabledValue, pluginRTASMultiMonoDisabledValue, pluginAUMainTypeValue, pluginRTASCategoryValue, pluginRTASBypassDisabledValue, pluginRTASMultiMonoDisabledValue,
pluginAAXIdentifierValue, pluginAAXCategoryValue, pluginAAXBypassDisabledValue, pluginAAXMultiMonoDisabledValue; pluginAAXIdentifierValue, pluginAAXCategoryValue, pluginAAXBypassDisabledValue, pluginAAXMultiMonoDisabledValue;
//==============================================================================
File tempDirectory = {};
bool openInIDEAfterSaving = false;
void askUserWhereToSaveProject();
void moveTemporaryDirectory (const File&);
//==============================================================================
bool hasSentGUIBuilderAnalyticsEvent = false;
//============================================================================== //==============================================================================
friend class Item; friend class Item;
ScopedPointer<EnabledModuleList> enabledModulesList; ScopedPointer<EnabledModuleList> enabledModulesList;

View file

@ -138,6 +138,32 @@ public:
return Result::ok(); return Result::ok();
} }
Result saveContentNeededForLiveBuild()
{
OwnedArray<LibraryModule> modules;
project.getModules().createRequiredModules (modules);
checkModuleValidity (modules);
if (errors.size() == 0)
{
writeAppConfigFile (modules, loadUserContentFromAppConfig());
writeBinaryDataFiles();
writeAppHeader (modules);
writeModuleCppWrappers (modules);
if (project.getProjectType().isAudioPlugin())
{
writePluginCharacteristicsFile();
writeAppConfigFile (modules, loadUserContentFromAppConfig());
}
return Result::ok();
}
return Result::fail (errors[0]);
}
Project::Item saveGeneratedFile (const String& filePath, const MemoryOutputStream& newData) Project::Item saveGeneratedFile (const String& filePath, const MemoryOutputStream& newData)
{ {
if (! generatedCodeFolder.createDirectory()) if (! generatedCodeFolder.createDirectory())

View file

@ -97,12 +97,6 @@ const uint8 graph[] = { 110,109,166,158,186,66,184,11,143,67,108,113,151,95,67,9
36,62,67,57,208,166,67,183,75,46,67,100,188,174,67,183,75,46,67,68,107,184,67,108,183,75,46,67,119,233,224,67,98,183,75,46,67,87,152,234,67,13,36,62,67,130,132,242,67,205,129,81,67,130,132,242,67,108,25,63,145,67,130,132,242,67,98,249,237,154,67,130, 36,62,67,57,208,166,67,183,75,46,67,100,188,174,67,183,75,46,67,68,107,184,67,108,183,75,46,67,119,233,224,67,98,183,75,46,67,87,152,234,67,13,36,62,67,130,132,242,67,205,129,81,67,130,132,242,67,108,25,63,145,67,130,132,242,67,98,249,237,154,67,130,
132,242,67,36,218,162,67,87,152,234,67,36,218,162,67,119,233,224,67,108,36,218,162,67,68,107,184,67,98,36,218,162,67,100,188,174,67,249,237,154,67,57,208,166,67,25,63,145,67,57,208,166,67,99,101,0,0 }; 132,242,67,36,218,162,67,87,152,234,67,36,218,162,67,119,233,224,67,108,36,218,162,67,68,107,184,67,98,36,218,162,67,100,188,174,67,249,237,154,67,57,208,166,67,25,63,145,67,57,208,166,67,99,101,0,0 };
//const uint8 exporter[] = { 110,109,253,221,132,67,144,191,123,65,98,211,214,32,67,144,191,123,65,105,218,146,66,8,213,167,66,10,213,39,66,90,82,50,67,108,224,205,195,66,90,82,50,67,98,141,191,251,66,210,69,227,66,55,143,62,67,24,93,136,66,253,221,132,67,24,93,136,66,98,3,145,183,
//67,24,93,136,66,183,198,223,67,130,89,22,67,183,198,223,67,0,0,122,67,98,183,198,223,67,5,179,175,67,59,177,182,67,185,232,215,67,253,221,132,67,185,232,215,67,98,55,143,62,67,185,232,215,67,142,191,251,66,138,46,193,67,224,205,195,66,211,214,160,67,
//108,9,213,39,66,211,214,160,67,98,77,91,143,66,189,10,208,67,211,214,32,67,2,34,242,67,253,221,132,67,2,34,242,67,98,109,141,197,67,2,34,242,67,0,0,250,67,112,175,189,67,0,0,250,67,254,255,121,67,98,0,0,250,67,60,66,241,66,109,141,197,67,144,191,123,
//65,253,221,132,67,144,191,123,65,99,109,196,78,64,67,211,214,160,67,108,69,23,159,67,254,255,121,67,108,195,78,64,67,88,82,50,67,108,195,78,64,67,13,136,90,67,108,0,0,0,0,13,136,90,67,108,0,0,0,0,191,155,141,67,108,196,78,64,67,191,155,141,67,108,196,
//78,64,67,211,214,160,67,99,101,0,0 };
const uint8 jigsaw[] = { 110,109,244,9,155,65,198,29,87,67,98,244,9,155,65,198,29,87,67,43,107,174,66,227,15,248,66,97,208,255,66,78,89,17,67,98,202,154,40,67,140,186,36,67,99,79,240,66,200,156,71,67,44,234,30,67,230,13,89,67,98,168,172,69,67,2,127,106,67,96,208,127,67,166,45, const uint8 jigsaw[] = { 110,109,244,9,155,65,198,29,87,67,98,244,9,155,65,198,29,87,67,43,107,174,66,227,15,248,66,97,208,255,66,78,89,17,67,98,202,154,40,67,140,186,36,67,99,79,240,66,200,156,71,67,44,234,30,67,230,13,89,67,98,168,172,69,67,2,127,106,67,96,208,127,67,166,45,
85,67,164,47,116,67,76,218,32,67,98,198,158,102,67,229,13,217,66,72,93,79,67,78,89,17,67,42,236,61,67,35,111,236,66,98,12,123,44,67,169,43,182,66,239,136,139,67,232,142,232,65,239,136,139,67,232,142,232,65,98,239,136,139,67,232,142,232,65,10,123,172, 85,67,164,47,116,67,76,218,32,67,98,198,158,102,67,229,13,217,66,72,93,79,67,78,89,17,67,42,236,61,67,35,111,236,66,98,12,123,44,67,169,43,182,66,239,136,139,67,232,142,232,65,239,136,139,67,232,142,232,65,98,239,136,139,67,232,142,232,65,10,123,172,
67,44,234,30,67,154,51,181,67,225,15,248,66,98,89,212,192,67,173,170,166,66,151,53,212,67,110,202,34,66,228,142,232,67,103,77,209,66,98,228,142,232,67,103,77,209,66,0,0,250,67,172,41,23,67,4,127,234,67,234,138,42,67,98,6,254,218,67,40,236,61,67,55,101, 67,44,234,30,67,154,51,181,67,225,15,248,66,98,89,212,192,67,173,170,166,66,151,53,212,67,110,202,34,66,228,142,232,67,103,77,209,66,98,228,142,232,67,103,77,209,66,0,0,250,67,172,41,23,67,4,127,234,67,234,138,42,67,98,6,254,218,67,40,236,61,67,55,101,
@ -146,8 +140,6 @@ const uint8 bug[] = { 110,109,169,227,237,67,143,189,46,67,108,94,183,187,67,17,
67,237,54,242,67,22,232,192,67,98,73,207,244,67,210,148,188,67,97,20,243,67,26,100,183,67,29,193,238,67,190,203,180,67,108,70,114,189,67,60,29,153,67,98,162,10,192,67,112,35,140,67,22,232,192,67,70,83,126,67,162,10,192,67,76,75,107,67,108,96,20,243,67, 67,237,54,242,67,22,232,192,67,98,73,207,244,67,210,148,188,67,97,20,243,67,26,100,183,67,29,193,238,67,190,203,180,67,108,70,114,189,67,60,29,153,67,98,162,10,192,67,112,35,140,67,22,232,192,67,70,83,126,67,162,10,192,67,76,75,107,67,108,96,20,243,67,
202,156,79,67,98,164,103,247,67,226,225,77,67,0,0,250,67,114,128,67,67,140,34,249,67,234,217,58,67,98,166,103,247,67,96,51,50,67,237,54,242,67,168,2,45,67,169,227,237,67,143,189,46,67,99,101,0,0 }; 202,156,79,67,98,164,103,247,67,226,225,77,67,0,0,250,67,114,128,67,67,140,34,249,67,234,217,58,67,98,166,103,247,67,96,51,50,67,237,54,242,67,168,2,45,67,169,227,237,67,143,189,46,67,99,101,0,0 };
//const uint8 play[] = { 110,109,84,227,213,64,188,116,205,65,108,43,135,194,65,0,0,120,65,108,84,227,213,64,14,45,170,64,108,84,227,213,64,188,116,205,65,99,101,0,0 };
const uint8 code[] = { 110,109,190,159,130,64,240,167,130,64,108,190,159,130,64,191,159,226,64,108,4,86,215,65,191,159,226,64,108,4,86,215,65,240,167,130,64,108,190,159,130,64,240,167,130,64,99,109,190,159,130,64,176,114,162,65,108,4,86,215,65,176,114,162,65,108,4,86,215,65, const uint8 code[] = { 110,109,190,159,130,64,240,167,130,64,108,190,159,130,64,191,159,226,64,108,4,86,215,65,191,159,226,64,108,4,86,215,65,240,167,130,64,108,190,159,130,64,240,167,130,64,99,109,190,159,130,64,176,114,162,65,108,4,86,215,65,176,114,162,65,108,4,86,215,65,
188,116,138,65,108,190,159,130,64,188,116,138,65,108,190,159,130,64,176,114,162,65,99,109,190,159,130,64,160,26,91,65,108,4,86,215,65,160,26,91,65,108,4,86,215,65,184,30,43,65,108,190,159,130,64,184,30,43,65,108,190,159,130,64,160,26,91,65,99,109,190, 188,116,138,65,108,190,159,130,64,188,116,138,65,108,190,159,130,64,176,114,162,65,99,109,190,159,130,64,160,26,91,65,108,4,86,215,65,160,26,91,65,108,4,86,215,65,184,30,43,65,108,190,159,130,64,184,30,43,65,108,190,159,130,64,160,26,91,65,99,109,190,
159,130,64,4,86,215,65,108,4,86,215,65,4,86,215,65,108,4,86,215,65,16,88,191,65,108,190,159,130,64,16,88,191,65,108,190,159,130,64,4,86,215,65,99,101,0,0 }; 159,130,64,4,86,215,65,108,4,86,215,65,4,86,215,65,108,4,86,215,65,16,88,191,65,108,190,159,130,64,16,88,191,65,108,190,159,130,64,4,86,215,65,99,101,0,0 };
@ -1038,26 +1030,6 @@ const uint8 settings[] = { 110,109,202,111,210,64,243,226,61,64,108,0,0,224,64,0
const uint8 singleModule[] = { 110,109,165,48,137,63,179,12,91,64,108,0,0,224,64,0,0,0,0,108,235,217,78,65,179,12,91,64,108,0,0,224,64,176,12,219,64,108,165,48,137,63,179,12,91,64,99,109,51,10,147,61,80,243,164,64,108,0,0,192,64,211,60,9,65,108,0,0,192,64,45,195,118,65,108,51,10,147, const uint8 singleModule[] = { 110,109,165,48,137,63,179,12,91,64,108,0,0,224,64,0,0,0,0,108,235,217,78,65,179,12,91,64,108,0,0,224,64,176,12,219,64,108,165,48,137,63,179,12,91,64,99,109,51,10,147,61,80,243,164,64,108,0,0,192,64,211,60,9,65,108,0,0,192,64,45,195,118,65,108,51,10,147,
61,0,0,64,65,108,51,10,147,61,80,243,164,64,99,109,235,217,94,65,80,243,164,64,108,235,217,94,65,0,0,64,65,108,0,0,0,65,45,195,118,65,108,0,0,0,65,211,60,9,65,108,235,217,94,65,80,243,164,64,99,101,0,0 }; 61,0,0,64,65,108,51,10,147,61,80,243,164,64,99,109,235,217,94,65,80,243,164,64,108,235,217,94,65,0,0,64,65,108,0,0,0,65,45,195,118,65,108,0,0,0,65,211,60,9,65,108,235,217,94,65,80,243,164,64,99,101,0,0 };
const uint8 buildNow[] = { 110,109,0,128,57,65,0,0,11,63,98,171,165,35,65,179,98,241,62,24,105,13,65,129,238,116,63,0,112,249,64,0,0,0,64,98,91,21,203,64,75,181,92,64,242,83,191,64,108,13,178,64,0,192,213,64,0,112,235,64,108,0,128,72,63,0,24,84,65,98,36,57,13,59,45,151,96,65,68,
51,13,59,211,216,116,65,0,128,72,63,0,172,128,65,98,102,57,200,63,150,235,134,65,78,35,53,64,150,235,134,65,0,32,103,64,0,172,128,65,108,0,24,24,65,0,0,35,65,98,59,204,52,65,87,61,46,65,246,166,86,65,10,81,40,65,0,216,109,65,0,32,17,65,98,196,117,128,
65,238,24,252,64,30,44,132,65,217,124,199,64,0,16,130,65,0,16,150,64,108,0,240,85,65,0,112,242,64,108,0,112,34,65,0,224,214,64,108,0,160,20,65,0,160,95,64,108,0,208,66,65,0,128,27,63,98,50,185,63,65,138,15,19,63,49,159,60,65,134,157,13,63,0,128,57,65,
0,0,11,63,99,101,0,0 };
const uint8 continuousBuildStart[] = { 110,109,0,16,55,65,0,128,53,63,98,76,48,50,65,24,205,49,63,88,83,45,65,191,4,50,63,0,128,40,65,0,0,54,63,98,192,47,221,64,7,199,101,63,113,249,100,64,108,248,76,64,0,192,16,64,0,48,218,64,108,0,224,76,64,0,48,229,64,98,19,172,152,64,120,86,54,64,157,
101,24,65,103,159,33,63,0,104,93,65,0,224,12,64,98,64,148,133,65,2,124,79,64,7,4,149,65,255,247,181,64,0,56,153,65,0,136,7,65,108,0,168,144,65,0,112,8,65,108,0,56,159,65,0,200,59,65,108,0,8,171,65,0,176,5,65,108,0,84,161,65,0,176,6,65,98,39,235,156,65,
182,193,167,64,118,99,139,65,136,68,28,64,0,232,98,65,0,128,161,63,98,134,113,84,65,142,198,110,63,28,175,69,65,184,152,64,63,0,16,55,65,0,128,53,63,99,109,0,152,8,65,0,96,195,64,98,29,15,4,65,249,102,195,64,0,0,0,65,166,157,202,64,0,0,0,65,0,16,215,
64,108,0,0,0,65,0,120,84,65,98,0,0,0,65,44,177,90,65,29,15,4,65,0,80,94,65,0,152,8,65,0,80,94,65,98,31,114,10,65,0,80,94,65,62,243,12,65,54,180,93,65,0,40,15,65,0,112,92,65,98,167,130,45,65,197,243,74,65,90,229,75,65,191,112,57,65,0,64,106,65,0,248,39,
65,98,72,217,113,65,117,149,35,65,80,241,113,65,139,106,28,65,0,88,106,65,0,8,24,65,98,113,239,75,65,65,143,6,65,153,136,45,65,118,24,234,64,0,32,15,65,0,32,199,64,98,61,235,12,65,147,151,196,64,31,114,10,65,0,96,195,64,0,152,8,65,0,96,195,64,99,109,
0,64,6,64,0,56,4,65,108,0,0,31,63,0,80,58,65,108,0,128,228,63,0,88,57,65,98,209,237,21,64,250,1,108,65,133,239,144,64,4,85,140,65,0,112,248,64,0,192,149,65,98,136,90,73,65,147,201,163,65,109,114,143,65,68,217,143,65,0,124,157,65,0,144,82,65,108,0,244,
149,65,0,24,77,65,98,251,100,137,65,49,13,137,65,98,186,70,65,5,203,154,65,0,184,1,65,0,60,142,65,98,142,44,168,64,25,238,133,65,64,34,85,64,173,230,100,65,0,32,51,64,0,128,56,65,108,0,192,122,64,0,144,55,65,108,0,64,6,64,0,56,4,65,99,101,0,0 };
const uint8 continuousBuildStop[] = { 110,109,0,16,55,65,0,128,53,63,98,76,48,50,65,24,205,49,63,88,83,45,65,191,4,50,63,0,128,40,65,0,0,54,63,98,192,47,221,64,7,199,101,63,113,249,100,64,108,248,76,64,0,192,16,64,0,48,218,64,108,0,224,76,64,0,48,229,64,98,19,172,152,64,120,86,54,64,157,
101,24,65,103,159,33,63,0,104,93,65,0,224,12,64,98,64,148,133,65,2,124,79,64,7,4,149,65,255,247,181,64,0,56,153,65,0,136,7,65,108,0,168,144,65,0,112,8,65,108,0,56,159,65,0,200,59,65,108,0,8,171,65,0,176,5,65,108,0,84,161,65,0,176,6,65,98,39,235,156,65,
182,193,167,64,118,99,139,65,136,68,28,64,0,232,98,65,0,128,161,63,98,134,113,84,65,142,198,110,63,28,175,69,65,184,152,64,63,0,16,55,65,0,128,53,63,99,109,0,0,0,65,0,0,224,64,108,0,0,0,65,0,0,80,65,108,0,0,96,65,0,0,80,65,108,0,0,96,65,0,0,224,64,108,
0,0,0,65,0,0,224,64,99,109,0,64,6,64,0,56,4,65,108,0,0,31,63,0,80,58,65,108,0,128,228,63,0,88,57,65,98,209,237,21,64,250,1,108,65,133,239,144,64,4,85,140,65,0,112,248,64,0,192,149,65,98,136,90,73,65,147,201,163,65,109,114,143,65,68,217,143,65,0,124,157,
65,0,144,82,65,108,0,244,149,65,0,24,77,65,98,251,100,137,65,49,13,137,65,98,186,70,65,5,203,154,65,0,184,1,65,0,60,142,65,98,142,44,168,64,25,238,133,65,64,34,85,64,173,230,100,65,0,32,51,64,0,128,56,65,108,0,192,122,64,0,144,55,65,108,0,64,6,64,0,56,
4,65,99,101,0,0 };
const uint8 edit[] = { 110,109,0,16,92,65,0,0,74,62,108,0,104,69,65,0,64,206,63,108,0,168,132,65,0,80,187,64,108,0,248,143,65,0,16,142,64,108,0,16,92,65,0,0,74,62,99,109,0,200,46,65,0,160,65,64,108,0,32,28,64,0,40,56,65,108,0,208,213,64,0,16,124,65,108,0,176,114,65,0,144,232, const uint8 edit[] = { 110,109,0,16,92,65,0,0,74,62,108,0,104,69,65,0,64,206,63,108,0,168,132,65,0,80,187,64,108,0,248,143,65,0,16,142,64,108,0,16,92,65,0,0,74,62,99,109,0,200,46,65,0,160,65,64,108,0,32,28,64,0,40,56,65,108,0,208,213,64,0,16,124,65,108,0,176,114,65,0,144,232,
64,108,0,200,46,65,0,160,65,64,99,109,0,192,135,63,0,56,78,65,108,0,0,160,60,0,96,145,65,108,0,176,169,64,0,12,137,65,108,0,192,135,63,0,56,78,65,99,101,0,0 }; 64,108,0,200,46,65,0,160,65,64,99,109,0,192,135,63,0,56,78,65,108,0,0,160,60,0,96,145,65,108,0,176,169,64,0,12,137,65,108,0,192,135,63,0,56,78,65,99,101,0,0 };
@ -1588,17 +1560,14 @@ Icons::Icons()
JUCE_LOAD_PATH_DATA (imageDoc) JUCE_LOAD_PATH_DATA (imageDoc)
JUCE_LOAD_PATH_DATA (config) JUCE_LOAD_PATH_DATA (config)
JUCE_LOAD_PATH_DATA (graph) JUCE_LOAD_PATH_DATA (graph)
// JUCE_LOAD_PATH_DATA (exporter)
JUCE_LOAD_PATH_DATA (jigsaw) JUCE_LOAD_PATH_DATA (jigsaw)
JUCE_LOAD_PATH_DATA (info) JUCE_LOAD_PATH_DATA (info)
JUCE_LOAD_PATH_DATA (warning) JUCE_LOAD_PATH_DATA (warning)
JUCE_LOAD_PATH_DATA (bug) JUCE_LOAD_PATH_DATA (bug)
// JUCE_LOAD_PATH_DATA (play)
JUCE_LOAD_PATH_DATA (code) JUCE_LOAD_PATH_DATA (code)
JUCE_LOAD_PATH_DATA (box) JUCE_LOAD_PATH_DATA (box)
JUCE_LOAD_PATH_DATA (juceLogo) JUCE_LOAD_PATH_DATA (juceLogo)
JUCE_LOAD_PATH_DATA (mainJuceLogo) JUCE_LOAD_PATH_DATA (mainJuceLogo)
JUCE_LOAD_PATH_DATA (user) JUCE_LOAD_PATH_DATA (user)
JUCE_LOAD_PATH_DATA (closedFolder) JUCE_LOAD_PATH_DATA (closedFolder)
JUCE_LOAD_PATH_DATA (exporter) JUCE_LOAD_PATH_DATA (exporter)
@ -1610,9 +1579,6 @@ Icons::Icons()
JUCE_LOAD_PATH_DATA (play) JUCE_LOAD_PATH_DATA (play)
JUCE_LOAD_PATH_DATA (settings) JUCE_LOAD_PATH_DATA (settings)
JUCE_LOAD_PATH_DATA (singleModule) JUCE_LOAD_PATH_DATA (singleModule)
JUCE_LOAD_PATH_DATA (buildNow)
JUCE_LOAD_PATH_DATA (continuousBuildStart)
JUCE_LOAD_PATH_DATA (continuousBuildStop)
JUCE_LOAD_PATH_DATA (edit) JUCE_LOAD_PATH_DATA (edit)
JUCE_LOAD_PATH_DATA (plus); JUCE_LOAD_PATH_DATA (plus);
JUCE_LOAD_PATH_DATA (android); JUCE_LOAD_PATH_DATA (android);

View file

@ -72,16 +72,10 @@ class Icons
public: public:
Icons(); Icons();
Path folder, document, imageDoc, Path folder, document, imageDoc, config, juceLogo, graph, jigsaw, info, warning, bug,
config, /*exporter,*/ juceLogo, code, box, mainJuceLogo, user, closedFolder, exporter, fileExplorer, file, buildTab,
graph, jigsaw, info, warning, modules, openFolder, play, settings, singleModule, edit, plus, android, codeBlocks,
bug, /*play,*/ code, box, linux, xcode, visualStudio, clion;
mainJuceLogo;
Path user, closedFolder, exporter, fileExplorer, file,
buildTab, modules, openFolder, play, settings, singleModule,
buildNow, continuousBuildStart, continuousBuildStop, edit, plus,
android, codeBlocks, linux, xcode, visualStudio, clion;
private: private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Icons) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Icons)

View file

@ -26,6 +26,8 @@
#pragma once #pragma once
#include "../../Licenses/jucer_LicenseController.h"
#include "../../Application/jucer_Application.h"
//============================================================================== //==============================================================================
class UserSettingsPopup : public Component class UserSettingsPopup : public Component

View file

@ -158,13 +158,15 @@ public:
// Handle Open Project button functionality // Handle Open Project button functionality
ApplicationCommandManager& commandManager = ProjucerApplication::getCommandManager(); ApplicationCommandManager& commandManager = ProjucerApplication::getCommandManager();
addAndMakeVisible (blankProjectButton = new TemplateOptionButton ("Create Blank Project", TemplateOptionButton::ImageOnButtonBackground, BinaryData::wizard_Openfile_svg)); addAndMakeVisible (blankProjectButton);
addAndMakeVisible (exampleProjectButton = new TemplateOptionButton ("Open Example Project", TemplateOptionButton::ImageOnButtonBackground, BinaryData::wizard_Openfile_svg)); addAndMakeVisible (openProjectButton);
addAndMakeVisible (openProjectButton = new TemplateOptionButton ("Open Existing Project", TemplateOptionButton::ImageOnButtonBackground, BinaryData::wizard_Openfile_svg)); addAndMakeVisible (browseDemosButton);
addAndMakeVisible (viewTutorialsButton);
blankProjectButton->onClick = [this] { createBlankProject(); }; blankProjectButton.onClick = [this] { createBlankProject(); };
exampleProjectButton->onClick = [this] { openExampleProject(); }; openProjectButton.setCommandToTrigger (&commandManager, CommandIDs::open, true);
openProjectButton->setCommandToTrigger (&commandManager, CommandIDs::open, true); browseDemosButton.setCommandToTrigger (&commandManager, CommandIDs::launchDemoRunner, true);
viewTutorialsButton.setCommandToTrigger (&commandManager, CommandIDs::showTutorials, true);
newProjectWizard = projectWizard; newProjectWizard = projectWizard;
} }
@ -185,35 +187,41 @@ public:
for (int i = 0; i < optionButtons.size(); ++i) for (int i = 0; i < optionButtons.size(); ++i)
if (optionButtons.getUnchecked(i)->isOver()) if (optionButtons.getUnchecked(i)->isOver())
g.drawFittedText (optionButtons.getUnchecked(i)->getDescription(), descriptionBox, Justification::centred, 5, 1.0f); g.drawFittedText (optionButtons.getUnchecked(i)->getDescription(), descriptionBox, Justification::centredBottom, 5, 1.0f);
} }
void resized() override void resized() override
{ {
auto allOpts = getLocalBounds().reduced (40, 60); auto bounds = getLocalBounds().reduced (40, 0);
allOpts.removeFromBottom (allOpts.getHeight() / 4); bounds.removeFromTop (60);
const auto numHorizIcons = 4;
const auto optStep = allOpts.getWidth() / numHorizIcons;
for (int i = 0; i < optionButtons.size(); ++i)
{ {
const auto yShift = i < numHorizIcons ? 0 : 1; auto optionBounds = bounds.removeFromTop (roundToInt (bounds.getHeight() * 0.65f));
optionButtons.getUnchecked(i)->setBounds (Rectangle<int> (allOpts.getX() + (i % numHorizIcons) * optStep, auto topSlice = optionBounds.removeFromTop (optionBounds.getHeight() / 2).reduced (0, 10);
allOpts.getY() + yShift * allOpts.getHeight() / 2, auto bottomSlice = optionBounds.reduced (0, 10);
optStep, allOpts.getHeight() / 2)
.reduced (10, 10)); const int numHorizontal = 4;
for (int i = 0; i < optionButtons.size(); ++i)
{
auto& sliceToUse = (i < numHorizontal ? topSlice : bottomSlice);
optionButtons.getUnchecked (i)->setBounds (sliceToUse.removeFromLeft (sliceToUse.getWidth() / (4 - (i % 4))).reduced (10, 0));
}
} }
auto openButtonBounds = getLocalBounds(); bounds.removeFromTop (20);
openButtonBounds.removeFromBottom (proportionOfHeight (0.12f)); auto topButtonBounds = bounds.removeFromTop (50);
openButtonBounds = openButtonBounds.removeFromBottom (120);
openButtonBounds.reduce (50, 40);
blankProjectButton->setBounds (openButtonBounds.removeFromLeft (optStep - 20)); openProjectButton.setBounds (topButtonBounds.reduced (80, 0));
exampleProjectButton->setBounds (openButtonBounds.removeFromRight (optStep - 20));
openProjectButton->setBounds (openButtonBounds.reduced (18, 0)); bounds.removeFromTop (10);
auto bottomButtonBounds = bounds.removeFromTop (35);
blankProjectButton.setBounds (bottomButtonBounds.removeFromLeft (bottomButtonBounds.getWidth() / 3).reduced (10, 0));
browseDemosButton.setBounds (bottomButtonBounds.removeFromLeft (bottomButtonBounds.getWidth() / 2).reduced (10, 0));
viewTutorialsButton.setBounds (bottomButtonBounds.removeFromLeft (bottomButtonBounds.getWidth()).reduced (10, 0));
} }
void showWizard (const String& name) void showWizard (const String& name)
@ -231,36 +239,14 @@ public:
showWizard (BlankAppWizard().getName()); showWizard (BlankAppWizard().getName());
} }
void openExampleProject()
{
FileChooser fc ("Open File", findExamplesFolder());
if (fc.browseForFileToOpen())
ProjucerApplication::getApp().openFile (fc.getResult());
}
static File findExamplesFolder()
{
File appFolder (File::getSpecialLocation (File::currentApplicationFile));
while (appFolder.exists()
&& appFolder.getParentDirectory() != appFolder)
{
File examples (appFolder.getSiblingFile ("examples"));
if (examples.exists())
return examples;
appFolder = appFolder.getParentDirectory();
}
return {};
}
private: private:
OwnedArray<TemplateOptionButton> optionButtons; OwnedArray<TemplateOptionButton> optionButtons;
NewProjectWizardClasses::WizardComp* newProjectWizard; NewProjectWizardClasses::WizardComp* newProjectWizard;
ScopedPointer<TemplateOptionButton> blankProjectButton, openProjectButton, exampleProjectButton;
TemplateOptionButton blankProjectButton { "Create Blank Project", TemplateOptionButton::ImageOnButtonBackground, BinaryData::wizard_Openfile_svg },
openProjectButton { "Open Existing Project", TemplateOptionButton::ImageOnButtonBackground, BinaryData::wizard_Openfile_svg },
browseDemosButton { "Browse JUCE Demos", TemplateOptionButton::ImageOnButtonBackground, BinaryData::wizard_Openfile_svg },
viewTutorialsButton { "View JUCE Tutorials", TemplateOptionButton::ImageOnButtonBackground, BinaryData::wizard_Openfile_svg };
void showWizardButton (Button* b) void showWizardButton (Button* b)
{ {