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:
parent
fa02112614
commit
47af78fe0b
31 changed files with 1256 additions and 457 deletions
|
|
@ -101,6 +101,7 @@ OBJECTS_APP := \
|
|||
$(JUCE_OBJDIR)/jucer_CompileEngineClient_aee8c99c.o \
|
||||
$(JUCE_OBJDIR)/jucer_CompileEngineServer_5d8914.o \
|
||||
$(JUCE_OBJDIR)/jucer_DownloadCompileEngineThread_19bb4bb3.o \
|
||||
$(JUCE_OBJDIR)/jucer_HeaderComponent_1ebf72ba.o \
|
||||
$(JUCE_OBJDIR)/jucer_Module_3f7666a5.o \
|
||||
$(JUCE_OBJDIR)/jucer_Project_c131864a.o \
|
||||
$(JUCE_OBJDIR)/jucer_ProjectExporter_cf377b25.o \
|
||||
|
|
@ -304,6 +305,11 @@ $(JUCE_OBJDIR)/jucer_DownloadCompileEngineThread_19bb4bb3.o: ../../Source/LiveBu
|
|||
@echo "Compiling jucer_DownloadCompileEngineThread.cpp"
|
||||
$(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
|
||||
-$(V_AT)mkdir -p $(JUCE_OBJDIR)
|
||||
@echo "Compiling jucer_Module.cpp"
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@
|
|||
D25EBE02B55DB244BE0D5635 = {isa = PBXBuildFile; fileRef = DE3E6B2614229FAD56D50770; };
|
||||
85E7FCB0516EFF853FA7B380 = {isa = PBXBuildFile; fileRef = D2FE76E4CF003856278343CC; };
|
||||
CC6C4D351BA9B473E5F95791 = {isa = PBXBuildFile; fileRef = ADA538034910F52FDD2DC88D; };
|
||||
05A08E366EBF8D650974E695 = {isa = PBXBuildFile; fileRef = 516D6D7C564DD5DF5C15CB06; };
|
||||
3FCA61C401007B243E2E9035 = {isa = PBXBuildFile; fileRef = F797071D88542C813CF7222A; };
|
||||
30B921C38DCEE787B294B746 = {isa = PBXBuildFile; fileRef = BAC43B20E14A340CCF14119C; };
|
||||
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"; };
|
||||
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"; };
|
||||
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"; };
|
||||
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"; };
|
||||
|
|
@ -633,6 +635,7 @@
|
|||
236D186F5A6536C59D6E751C,
|
||||
32ECBC08D903418CA0825870,
|
||||
A509BC22854D50E4C786EB32,
|
||||
516D6D7C564DD5DF5C15CB06,
|
||||
16751E04B0F3737BDF52CEB4,
|
||||
B3528C08B84CBC950252EA69,
|
||||
1B0F18E1D96F727C062B05FA,
|
||||
|
|
@ -964,6 +967,7 @@
|
|||
D25EBE02B55DB244BE0D5635,
|
||||
85E7FCB0516EFF853FA7B380,
|
||||
CC6C4D351BA9B473E5F95791,
|
||||
05A08E366EBF8D650974E695,
|
||||
3FCA61C401007B243E2E9035,
|
||||
30B921C38DCEE787B294B746,
|
||||
244567D3AE2E417A8CB2B95E,
|
||||
|
|
|
|||
|
|
@ -226,6 +226,7 @@
|
|||
<ClCompile Include="..\..\Source\LiveBuildEngine\jucer_CompileEngineClient.cpp"/>
|
||||
<ClCompile Include="..\..\Source\LiveBuildEngine\jucer_CompileEngineServer.cpp"/>
|
||||
<ClCompile Include="..\..\Source\LiveBuildEngine\jucer_DownloadCompileEngineThread.cpp"/>
|
||||
<ClCompile Include="..\..\Source\Project\UI\jucer_HeaderComponent.cpp"/>
|
||||
<ClCompile Include="..\..\Source\Project\UI\jucer_ProjectContentComponent.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -442,6 +442,9 @@
|
|||
<ClCompile Include="..\..\Source\LiveBuildEngine\jucer_DownloadCompileEngineThread.cpp">
|
||||
<Filter>Projucer\LiveBuildEngine</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\Source\Project\UI\jucer_HeaderComponent.cpp">
|
||||
<Filter>Projucer\Project\UI</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\Source\Project\UI\jucer_ProjectContentComponent.cpp">
|
||||
<Filter>Projucer\Project\UI</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -226,6 +226,7 @@
|
|||
<ClCompile Include="..\..\Source\LiveBuildEngine\jucer_CompileEngineClient.cpp"/>
|
||||
<ClCompile Include="..\..\Source\LiveBuildEngine\jucer_CompileEngineServer.cpp"/>
|
||||
<ClCompile Include="..\..\Source\LiveBuildEngine\jucer_DownloadCompileEngineThread.cpp"/>
|
||||
<ClCompile Include="..\..\Source\Project\UI\jucer_HeaderComponent.cpp"/>
|
||||
<ClCompile Include="..\..\Source\Project\UI\jucer_ProjectContentComponent.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -442,6 +442,9 @@
|
|||
<ClCompile Include="..\..\Source\LiveBuildEngine\jucer_DownloadCompileEngineThread.cpp">
|
||||
<Filter>Projucer\LiveBuildEngine</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\Source\Project\UI\jucer_HeaderComponent.cpp">
|
||||
<Filter>Projucer\Project\UI</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\Source\Project\UI\jucer_ProjectContentComponent.cpp">
|
||||
<Filter>Projucer\Project\UI</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -226,6 +226,7 @@
|
|||
<ClCompile Include="..\..\Source\LiveBuildEngine\jucer_CompileEngineClient.cpp"/>
|
||||
<ClCompile Include="..\..\Source\LiveBuildEngine\jucer_CompileEngineServer.cpp"/>
|
||||
<ClCompile Include="..\..\Source\LiveBuildEngine\jucer_DownloadCompileEngineThread.cpp"/>
|
||||
<ClCompile Include="..\..\Source\Project\UI\jucer_HeaderComponent.cpp"/>
|
||||
<ClCompile Include="..\..\Source\Project\UI\jucer_ProjectContentComponent.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -442,6 +442,9 @@
|
|||
<ClCompile Include="..\..\Source\LiveBuildEngine\jucer_DownloadCompileEngineThread.cpp">
|
||||
<Filter>Projucer\LiveBuildEngine</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\Source\Project\UI\jucer_HeaderComponent.cpp">
|
||||
<Filter>Projucer\Project\UI</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\Source\Project\UI\jucer_ProjectContentComponent.cpp">
|
||||
<Filter>Projucer\Project\UI</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -542,6 +542,8 @@
|
|||
resource="0" file="Source/Project/UI/jucer_ContentViewComponents.h"/>
|
||||
<FILE id="wFypDd" name="jucer_FileGroupInformationComponent.h" compile="0"
|
||||
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="Source/Project/UI/jucer_HeaderComponent.h"/>
|
||||
<FILE id="dN0Xzo" name="jucer_ModulesInformationComponent.h" compile="0"
|
||||
|
|
|
|||
|
|
@ -28,25 +28,12 @@
|
|||
|
||||
|
||||
//==============================================================================
|
||||
class GlobalSearchPathsWindowComponent : public Component
|
||||
class GlobalPathsWindowComponent : public Component
|
||||
{
|
||||
public:
|
||||
GlobalSearchPathsWindowComponent()
|
||||
: modulesLabel ("modulesLabel", "Modules"),
|
||||
sdksLabel ("sdksLabel", "SDKs"),
|
||||
cLionLabel ("cLionLabel", "CLion")
|
||||
GlobalPathsWindowComponent()
|
||||
{
|
||||
addAndMakeVisible (modulesLabel);
|
||||
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);
|
||||
addLabelsAndSetProperties();
|
||||
|
||||
addAndMakeVisible (info);
|
||||
info.setInfoToDisplay ("Use this dropdown to set the global paths for different OSes. "
|
||||
|
|
@ -59,7 +46,11 @@ public:
|
|||
osSelector.addItem ("Windows", 2);
|
||||
osSelector.addItem ("Linux", 3);
|
||||
|
||||
osSelector.onChange = [this] { updateFilePathPropertyComponents(); };
|
||||
osSelector.onChange = [this]
|
||||
{
|
||||
addLabelsAndSetProperties();
|
||||
updateFilePathPropertyComponents();
|
||||
};
|
||||
|
||||
auto os = TargetOS::getThisOS();
|
||||
|
||||
|
|
@ -85,40 +76,33 @@ public:
|
|||
|
||||
info.setBounds (osSelector.getBounds().withWidth (osSelector.getHeight()).translated ((osSelector.getWidth() + 5), 0).reduced (2));
|
||||
|
||||
modulesLabel.setBounds (b.removeFromTop (20));
|
||||
b.removeFromTop (20);
|
||||
|
||||
auto thisOS = TargetOS::getThisOS();
|
||||
auto selectedOS = getSelectedOS();
|
||||
const int numComps = pathPropertyComponents.size();
|
||||
|
||||
for (int i = 0; i < numComps; ++i)
|
||||
int labelIndex = 0;
|
||||
for (auto* pathComp : pathPropertyComponents)
|
||||
{
|
||||
pathPropertyComponents[i]->setBounds (b.removeFromTop (pathPropertyComponents[i]->getPreferredHeight()));
|
||||
b.removeFromTop (5);
|
||||
|
||||
if (i == 1)
|
||||
if (pathComp == nullptr)
|
||||
{
|
||||
b.removeFromTop (15);
|
||||
sdksLabel.setBounds (b.removeFromTop (20));
|
||||
pathPropertyLabels.getUnchecked (labelIndex++)->setBounds (b.removeFromTop (20));
|
||||
b.removeFromTop (20);
|
||||
}
|
||||
|
||||
if (selectedOS == thisOS && i == numComps - 2)
|
||||
else
|
||||
{
|
||||
b.removeFromTop (15);
|
||||
cLionLabel.setBounds (b.removeFromTop (20));
|
||||
b.removeFromTop (20);
|
||||
pathComp->setBounds (b.removeFromTop (pathComp->getPreferredHeight()));
|
||||
b.removeFromTop (5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Label modulesLabel, sdksLabel, cLionLabel;
|
||||
OwnedArray<Label> pathPropertyLabels;
|
||||
OwnedArray<PropertyComponent> pathPropertyComponents;
|
||||
|
||||
ComboBox osSelector;
|
||||
InfoButton info;
|
||||
|
||||
//==============================================================================
|
||||
bool isSelectedOSThisOS() { return TargetOS::getThisOS() == getSelectedOS(); }
|
||||
|
||||
TargetOS::OS getSelectedOS() const
|
||||
{
|
||||
auto selectedOS = TargetOS::unknown;
|
||||
|
|
@ -138,27 +122,28 @@ private:
|
|||
{
|
||||
pathPropertyComponents.clear();
|
||||
|
||||
const auto thisOS = TargetOS::getThisOS();
|
||||
const auto selectedOS = getSelectedOS();
|
||||
|
||||
auto& settings = getAppSettings();
|
||||
|
||||
if (selectedOS == thisOS)
|
||||
if (isSelectedOSThisOS())
|
||||
{
|
||||
pathPropertyComponents.add (nullptr);
|
||||
|
||||
addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (settings.getStoredPath (Ids::defaultJuceModulePath),
|
||||
"JUCE Modules", true)));
|
||||
addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (settings.getStoredPath (Ids::defaultUserModulePath),
|
||||
"User Modules", true, {}, {}, true)));
|
||||
|
||||
pathPropertyComponents.add (nullptr);
|
||||
|
||||
addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (settings.getStoredPath (Ids::vst3Path),
|
||||
"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);
|
||||
|
||||
addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (Value(), "AAX SDK", true)));
|
||||
addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent ({}, "AAX SDK", true)));
|
||||
pathPropertyComponents.getLast()->setEnabled (false);
|
||||
}
|
||||
else
|
||||
|
|
@ -174,6 +159,8 @@ private:
|
|||
addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (settings.getStoredPath (Ids::androidNDKPath),
|
||||
"Android NDK", true)));
|
||||
|
||||
pathPropertyComponents.add (nullptr);
|
||||
|
||||
#if JUCE_MAC
|
||||
String exeLabel ("app");
|
||||
#elif JUCE_WINDOWS
|
||||
|
|
@ -186,13 +173,18 @@ private:
|
|||
}
|
||||
else
|
||||
{
|
||||
auto selectedOS = getSelectedOS();
|
||||
auto maxChars = 1024;
|
||||
|
||||
pathPropertyComponents.add (nullptr);
|
||||
|
||||
addAndMakeVisible (pathPropertyComponents.add (new TextPropertyComponent (settings.getFallbackPathForOS (Ids::defaultJuceModulePath, selectedOS),
|
||||
"JUCE Modules", maxChars, false)));
|
||||
addAndMakeVisible (pathPropertyComponents.add (new TextPropertyComponent (settings.getFallbackPathForOS (Ids::defaultUserModulePath, selectedOS),
|
||||
"User Modules", maxChars, false)));
|
||||
|
||||
pathPropertyComponents.add (nullptr);
|
||||
|
||||
addAndMakeVisible (pathPropertyComponents.add (new TextPropertyComponent (settings.getFallbackPathForOS (Ids::vst3Path, selectedOS),
|
||||
"VST3 SDK", maxChars, false)));
|
||||
|
||||
|
|
@ -207,19 +199,35 @@ private:
|
|||
else
|
||||
{
|
||||
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),
|
||||
"AAX SDK", maxChars, false)));
|
||||
"AAX SDK", maxChars, false)));
|
||||
}
|
||||
|
||||
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),
|
||||
"Android NDK", maxChars, false)));
|
||||
"Android NDK", maxChars, false)));
|
||||
}
|
||||
|
||||
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)
|
||||
};
|
||||
|
|
@ -224,6 +224,10 @@ void ProjucerApplication::shutdown()
|
|||
|
||||
LookAndFeel::setDefaultLookAndFeel (nullptr);
|
||||
|
||||
// clean up after ourselves and delete any temp project files that may have
|
||||
// been created from PIPs
|
||||
deleteTemporaryFiles();
|
||||
|
||||
if (! isRunningCommandLine)
|
||||
Logger::writeToLog ("Shutdown");
|
||||
|
||||
|
|
@ -332,7 +336,8 @@ enum
|
|||
openWindowsBaseID = 300,
|
||||
activeDocumentsBaseID = 400,
|
||||
colourSchemeBaseID = 1000,
|
||||
codeEditorColourSchemeBaseID = 2000,
|
||||
codeEditorColourSchemeBaseID = 1500,
|
||||
examplesBaseID = 2000,
|
||||
};
|
||||
|
||||
MenuBarModel* ProjucerApplication::getMenuModel()
|
||||
|
|
@ -362,6 +367,7 @@ void ProjucerApplication::createMenu (PopupMenu& menu, const String& menuName)
|
|||
void ProjucerApplication::createFileMenu (PopupMenu& menu)
|
||||
{
|
||||
menu.addCommandItem (commandManager, CommandIDs::newProject);
|
||||
menu.addCommandItem (commandManager, CommandIDs::newProjectFromClipboard);
|
||||
menu.addSeparator();
|
||||
menu.addCommandItem (commandManager, CommandIDs::open);
|
||||
|
||||
|
|
@ -379,6 +385,13 @@ void ProjucerApplication::createFileMenu (PopupMenu& menu)
|
|||
menu.addSubMenu ("Open Recent", recentFiles);
|
||||
}
|
||||
|
||||
{
|
||||
PopupMenu examples;
|
||||
|
||||
createExamplesPopupMenu (examples);
|
||||
menu.addSubMenu ("Open Example", examples);
|
||||
}
|
||||
|
||||
menu.addSeparator();
|
||||
menu.addCommandItem (commandManager, CommandIDs::closeDocument);
|
||||
menu.addCommandItem (commandManager, CommandIDs::saveDocument);
|
||||
|
|
@ -554,6 +567,244 @@ void ProjucerApplication::createExtraAppleMenuItems (PopupMenu& menu)
|
|||
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)
|
||||
{
|
||||
if (menuItemID >= recentProjectsBaseID && menuItemID < (recentProjectsBaseID + 100))
|
||||
|
|
@ -586,6 +837,10 @@ void ProjucerApplication::handleMainMenuCommand (int menuItemID)
|
|||
{
|
||||
showEditorColourSchemeWindow();
|
||||
}
|
||||
else if (menuItemID >= examplesBaseID && menuItemID < (examplesBaseID + numExamples))
|
||||
{
|
||||
findAndLaunchExample (menuItemID - examplesBaseID);
|
||||
}
|
||||
else
|
||||
{
|
||||
handleGUIEditorMenuCommand (menuItemID);
|
||||
|
|
@ -598,7 +853,9 @@ void ProjucerApplication::getAllCommands (Array <CommandID>& commands)
|
|||
JUCEApplication::getAllCommands (commands);
|
||||
|
||||
const CommandID ids[] = { CommandIDs::newProject,
|
||||
CommandIDs::newProjectFromClipboard,
|
||||
CommandIDs::open,
|
||||
CommandIDs::launchDemoRunner,
|
||||
CommandIDs::closeAllWindows,
|
||||
CommandIDs::closeAllDocuments,
|
||||
CommandIDs::clearRecentFiles,
|
||||
|
|
@ -622,18 +879,38 @@ void ProjucerApplication::getCommandInfo (CommandID commandID, ApplicationComman
|
|||
switch (commandID)
|
||||
{
|
||||
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));
|
||||
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:
|
||||
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));
|
||||
break;
|
||||
|
||||
case CommandIDs::showGlobalPathsWindow:
|
||||
result.setInfo ("Global Search Paths...",
|
||||
"Shows the window to change the global search paths.",
|
||||
result.setInfo ("Global Paths...",
|
||||
"Shows the window to change the stored global paths.",
|
||||
CommandCategories::general, 0);
|
||||
break;
|
||||
|
||||
|
|
@ -719,7 +996,9 @@ bool ProjucerApplication::perform (const InvocationInfo& info)
|
|||
switch (info.commandID)
|
||||
{
|
||||
case CommandIDs::newProject: createNewProject(); break;
|
||||
case CommandIDs::newProjectFromClipboard: createNewProjectFromClipboard(); break;
|
||||
case CommandIDs::open: askUserToOpenFile(); break;
|
||||
case CommandIDs::launchDemoRunner: launchDemoRunner(); break;
|
||||
case CommandIDs::saveAll: openDocumentManager.saveAll(); break;
|
||||
case CommandIDs::closeAllWindows: closeAllMainWindowsAndQuitIfNeeded(); break;
|
||||
case CommandIDs::closeAllDocuments: closeAllDocuments (true); break;
|
||||
|
|
@ -743,11 +1022,30 @@ bool ProjucerApplication::perform (const InvocationInfo& info)
|
|||
//==============================================================================
|
||||
void ProjucerApplication::createNewProject()
|
||||
{
|
||||
MainWindow* mw = mainWindowList.getOrCreateEmptyWindow();
|
||||
mw->showNewProjectWizard();
|
||||
auto* mw = mainWindowList.getOrCreateEmptyWindow();
|
||||
mw->showStartPage();
|
||||
|
||||
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)
|
||||
{
|
||||
LiveBuildProjectSettings::updateNewlyOpenedProject (p);
|
||||
|
|
@ -850,10 +1148,10 @@ void ProjucerApplication::showPathsWindow()
|
|||
if (pathsWindow != nullptr)
|
||||
pathsWindow->toFront (true);
|
||||
else
|
||||
new FloatingToolWindow ("Global Search Paths",
|
||||
new FloatingToolWindow ("Global Paths",
|
||||
"pathsWindowPos",
|
||||
new GlobalSearchPathsWindowComponent(), pathsWindow, false,
|
||||
600, 500, 600, 500, 600, 500);
|
||||
new GlobalPathsWindowComponent(), pathsWindow, false,
|
||||
600, 550, 600, 550, 600, 550);
|
||||
}
|
||||
|
||||
void ProjucerApplication::showEditorColourSchemeWindow()
|
||||
|
|
@ -980,6 +1278,14 @@ void ProjucerApplication::initCommandManager()
|
|||
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)
|
||||
{
|
||||
auto& appearanceSettings = getAppSettings().appearance;
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ public:
|
|||
|
||||
//==============================================================================
|
||||
void createNewProject();
|
||||
void createNewProjectFromClipboard();
|
||||
void updateNewlyOpenedProject (Project&);
|
||||
void askUserToOpenFile();
|
||||
bool openFile (const File&);
|
||||
|
|
@ -166,6 +167,26 @@ private:
|
|||
void handleAsyncUpdate() override;
|
||||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -34,10 +34,13 @@ namespace CommandIDs
|
|||
enum
|
||||
{
|
||||
newProject = 0x300000,
|
||||
open = 0x300001,
|
||||
closeDocument = 0x300002,
|
||||
saveDocument = 0x300003,
|
||||
saveDocumentAs = 0x300004,
|
||||
newProjectFromClipboard = 0x300001,
|
||||
open = 0x300002,
|
||||
closeDocument = 0x300003,
|
||||
saveDocument = 0x300004,
|
||||
saveDocumentAs = 0x300005,
|
||||
|
||||
launchDemoRunner = 0x300006,
|
||||
|
||||
closeProject = 0x300010,
|
||||
saveProject = 0x300011,
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "jucer_Headers.h"
|
||||
#include "../Project/jucer_Module.h"
|
||||
#include "../Utility/Helpers/jucer_TranslationHelpers.h"
|
||||
#include "../Utility/PIPs/jucer_PIPGenerator.h"
|
||||
|
||||
#include "jucer_CommandLine.h"
|
||||
|
||||
|
|
@ -34,8 +35,6 @@
|
|||
//==============================================================================
|
||||
namespace
|
||||
{
|
||||
static const char* getLineEnding() { return "\r\n"; }
|
||||
|
||||
struct CommandLineError
|
||||
{
|
||||
CommandLineError (const String& s) : message (s) {}
|
||||
|
|
@ -749,6 +748,31 @@ namespace
|
|||
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()
|
||||
{
|
||||
|
|
@ -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
|
||||
<< 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
|
||||
<< 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -849,6 +876,7 @@ int performCommandLine (const String& commandLine)
|
|||
if (matchArgument (command, "trans")) { scanFoldersForTranslationFiles (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, "create-project-from-pip")) { createProjectFromPIP (args); return 0; }
|
||||
}
|
||||
catch (const CommandLineError& error)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
#include "Windows/jucer_AboutWindowComponent.h"
|
||||
#include "Windows/jucer_ApplicationUsageDataWindowComponent.h"
|
||||
#include "Windows/jucer_EditorColourSchemeWindowComponent.h"
|
||||
#include "Windows/jucer_GlobalSearchPathsWindowComponent.h"
|
||||
#include "Windows/jucer_GlobalPathsWindowComponent.h"
|
||||
#include "Windows/jucer_FloatingToolWindow.h"
|
||||
|
||||
#include "../LiveBuildEngine/jucer_MessageIDs.h"
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
#include "jucer_MainWindow.h"
|
||||
#include "../Wizards/jucer_NewProjectWizardClasses.h"
|
||||
#include "../Utility/UI/jucer_JucerTreeViewBase.h"
|
||||
|
||||
#include "../ProjectSaving/jucer_ProjectSaver.h"
|
||||
|
||||
//==============================================================================
|
||||
MainWindow::MainWindow()
|
||||
|
|
@ -140,7 +140,7 @@ void MainWindow::closeButtonPressed()
|
|||
ProjucerApplication::getApp().mainWindowList.closeWindow (this);
|
||||
}
|
||||
|
||||
bool MainWindow::closeProject (Project* project)
|
||||
bool MainWindow::closeProject (Project* project, bool askUserToSave)
|
||||
{
|
||||
jassert (project == currentProject && project != nullptr);
|
||||
|
||||
|
|
@ -156,12 +156,10 @@ bool MainWindow::closeProject (Project* project)
|
|||
pcc->hideEditor();
|
||||
}
|
||||
|
||||
if (! ProjucerApplication::getApp().openDocumentManager.closeAllDocumentsUsingProject (*project, true))
|
||||
if (! ProjucerApplication::getApp().openDocumentManager.closeAllDocumentsUsingProject (*project, askUserToSave))
|
||||
return false;
|
||||
|
||||
auto r = project->saveIfNeededAndUserAgrees();
|
||||
|
||||
if (r == FileBasedDocument::savedOk)
|
||||
if (! askUserToSave || (project->saveIfNeededAndUserAgrees() == FileBasedDocument::savedOk))
|
||||
{
|
||||
setProject (nullptr);
|
||||
return true;
|
||||
|
|
@ -175,6 +173,21 @@ bool MainWindow::closeCurrentProject()
|
|||
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)
|
||||
{
|
||||
createProjectContentCompIfNeeded();
|
||||
|
|
@ -186,6 +199,12 @@ void MainWindow::setProject (Project* newProject)
|
|||
else
|
||||
projectNameValue.referTo (Value());
|
||||
|
||||
if (newProject != nullptr)
|
||||
{
|
||||
if (auto* peer = getPeer())
|
||||
peer->setRepresentedFile (newProject->getFile());
|
||||
}
|
||||
|
||||
ProjucerApplication::getCommandManager().commandStatusChanged();
|
||||
}
|
||||
|
||||
|
|
@ -241,6 +260,142 @@ bool MainWindow::openFile (const File& file)
|
|||
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)
|
||||
{
|
||||
for (auto& filename : filenames)
|
||||
|
|
@ -256,7 +411,10 @@ void MainWindow::filesDropped (const StringArray& filenames, int /*mouseX*/, int
|
|||
{
|
||||
const File f (filename);
|
||||
|
||||
if (canOpenFile (f) && openFile (f))
|
||||
if (tryToOpenPIP (f))
|
||||
continue;
|
||||
|
||||
if (! isPIPFile (f) && (canOpenFile (f) && openFile (f)))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -326,9 +484,15 @@ void MainWindow::activeWindowStatusChanged()
|
|||
{
|
||||
if (auto* project = getProject())
|
||||
{
|
||||
auto oldTemporaryDirectory = project->getTemporaryDirectory();
|
||||
|
||||
auto projectFile = project->getFile();
|
||||
setProject (nullptr);
|
||||
openFile (projectFile);
|
||||
|
||||
if (oldTemporaryDirectory != File())
|
||||
if (auto* newProject = getProject())
|
||||
newProject->setTemporaryDirectory (oldTemporaryDirectory);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -340,13 +504,16 @@ void MainWindow::activeWindowStatusChanged()
|
|||
}
|
||||
}
|
||||
|
||||
void MainWindow::showNewProjectWizard()
|
||||
void MainWindow::showStartPage()
|
||||
{
|
||||
jassert (currentProject == nullptr);
|
||||
|
||||
setContentOwned (createNewProjectWizardComponent(), true);
|
||||
|
||||
centreWithSize (900, 630);
|
||||
setVisible (true);
|
||||
addToDesktop();
|
||||
|
||||
getContentComponent()->grabKeyboardFocus();
|
||||
}
|
||||
|
||||
|
|
@ -453,7 +620,7 @@ bool MainWindowList::askAllWindowsToClose()
|
|||
void MainWindowList::createWindowIfNoneAreOpen()
|
||||
{
|
||||
if (windows.size() == 0)
|
||||
createNewMainWindow()->showNewProjectWizard();
|
||||
createNewMainWindow()->showStartPage();
|
||||
}
|
||||
|
||||
void MainWindowList::closeWindow (MainWindow* w)
|
||||
|
|
@ -542,7 +709,10 @@ bool MainWindowList::openFile (const File& file, bool openInBackground)
|
|||
return ok;
|
||||
}
|
||||
|
||||
if (file.exists())
|
||||
if (getFrontmostWindow()->tryToOpenPIP (file))
|
||||
return true;
|
||||
|
||||
if (! isPIPFile (file) && file.exists())
|
||||
return getFrontmostWindow()->openFile (file);
|
||||
|
||||
return false;
|
||||
|
|
@ -599,6 +769,23 @@ MainWindow* MainWindowList::getOrCreateEmptyWindow()
|
|||
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)
|
||||
{
|
||||
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* p = mw->getProject())
|
||||
projects.add (p->getFile());
|
||||
if (! p->isTemporaryProject())
|
||||
projects.add (p->getFile());
|
||||
}
|
||||
|
||||
getAppSettings().setLastProjects (projects);
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Project/UI/jucer_ProjectContentComponent.h"
|
||||
#include "../Utility/PIPs/jucer_PIPGenerator.h"
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
|
|
@ -51,13 +52,15 @@ public:
|
|||
bool openFile (const File& file);
|
||||
void setProject (Project* newProject);
|
||||
Project* getProject() const { return currentProject.get(); }
|
||||
bool tryToOpenPIP (const File& f);
|
||||
|
||||
void makeVisible();
|
||||
void restoreWindowPosition();
|
||||
bool closeProject (Project* project);
|
||||
bool closeProject (Project* project, bool askToSave = true);
|
||||
bool closeCurrentProject();
|
||||
void moveProject (File newProjectFile);
|
||||
|
||||
void showNewProjectWizard();
|
||||
void showStartPage();
|
||||
|
||||
bool isInterestedInFileDrag (const StringArray& files) override;
|
||||
void filesDropped (const StringArray& filenames, int mouseX, int mouseY) override;
|
||||
|
|
@ -82,6 +85,8 @@ private:
|
|||
void createProjectContentCompIfNeeded();
|
||||
void setTitleBarIcon();
|
||||
|
||||
void openPIP (PIPGenerator&, StringRef fileName);
|
||||
|
||||
void valueChanged (Value&) override;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainWindow)
|
||||
|
|
@ -106,6 +111,7 @@ public:
|
|||
MainWindow* createNewMainWindow();
|
||||
MainWindow* getFrontmostWindow (bool createIfNotFound = true);
|
||||
MainWindow* getOrCreateEmptyWindow();
|
||||
MainWindow* getMainWindowForFile (const File&);
|
||||
|
||||
Project* getFrontmostProject();
|
||||
|
||||
|
|
|
|||
|
|
@ -684,6 +684,11 @@ void CompileEngineChildProcess::handleAppQuit()
|
|||
runningAppProcess.reset();
|
||||
}
|
||||
|
||||
bool CompileEngineChildProcess::isAppRunning() const noexcept
|
||||
{
|
||||
return runningAppProcess != nullptr && runningAppProcess->isRunningApp;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
struct CompileEngineChildProcess::Editor : private CodeDocument::Listener,
|
||||
private Timer
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ public:
|
|||
void launchApp();
|
||||
bool canKillApp() const;
|
||||
void killApp();
|
||||
bool isAppRunning() const noexcept;
|
||||
|
||||
const ClassDatabase::ClassList& getComponentList() const { return lastComponentList; }
|
||||
|
||||
|
|
|
|||
|
|
@ -192,8 +192,8 @@ private:
|
|||
|
||||
globalPathValue.referTo (modules.getShouldUseGlobalPathValue (moduleID));
|
||||
|
||||
auto menuItemString = (TargetOS::getThisOS() == TargetOS::osx ? "\"Projucer->Global Search Paths...\""
|
||||
: "\"File->Global Search Paths...\"");
|
||||
auto menuItemString = (TargetOS::getThisOS() == TargetOS::osx ? "\"Projucer->Global Paths...\""
|
||||
: "\"File->Global Paths...\"");
|
||||
|
||||
props.add (new BooleanPropertyComponent (globalPathValue,
|
||||
"Use global path", "Use global path for this module"),
|
||||
|
|
|
|||
372
extras/Projucer/Source/Project/UI/jucer_HeaderComponent.cpp
Normal file
372
extras/Projucer/Source/Project/UI/jucer_HeaderComponent.cpp
Normal 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);
|
||||
}
|
||||
|
|
@ -26,205 +26,48 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../../Application/jucer_Headers.h"
|
||||
#include "../../Utility/UI/jucer_IconButton.h"
|
||||
#include "../../Utility/UI/jucer_UserSettingsPopup.h"
|
||||
|
||||
class Project;
|
||||
|
||||
//==============================================================================
|
||||
class HeaderComponent : public Component,
|
||||
private ValueTree::Listener,
|
||||
private ChangeListener
|
||||
private ChangeListener,
|
||||
private Timer
|
||||
{
|
||||
public:
|
||||
HeaderComponent()
|
||||
: configLabel ("Config Label", "Selected exporter")
|
||||
{
|
||||
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;
|
||||
HeaderComponent();
|
||||
~HeaderComponent();
|
||||
|
||||
//==========================================================================
|
||||
void changeListenerCallback (ChangeBroadcaster* source) override
|
||||
{
|
||||
if (source == project)
|
||||
{
|
||||
updateName();
|
||||
updateExporters();
|
||||
}
|
||||
}
|
||||
void resized() override;
|
||||
void paint (Graphics&) override;
|
||||
|
||||
//==========================================================================
|
||||
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 valueTreeParentChanged (ValueTree&) override {}
|
||||
|
||||
|
|
@ -232,94 +75,41 @@ private:
|
|||
void valueTreeChildRemoved (ValueTree& parentTree, ValueTree&, int) override { updateIfNeeded (parentTree); }
|
||||
void valueTreeChildOrderChanged (ValueTree& parentTree, int, int) override { updateIfNeeded (parentTree); }
|
||||
|
||||
void initialiseButtons()
|
||||
{
|
||||
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)
|
||||
void updateIfNeeded (ValueTree tree) noexcept
|
||||
{
|
||||
if (tree == exportersTree)
|
||||
updateExporters();
|
||||
}
|
||||
|
||||
void updateName()
|
||||
{
|
||||
projectNameLabel.setText (project->getDocumentTitle(), dontSendNotification);
|
||||
}
|
||||
//==========================================================================
|
||||
void initialiseButtons() noexcept;
|
||||
|
||||
void updateExporterButton()
|
||||
{
|
||||
auto currentExporterName = getSelectedExporterName();
|
||||
void updateName() noexcept;
|
||||
void updateExporterButton() noexcept;
|
||||
void updateUserAvatar() noexcept;
|
||||
|
||||
for (auto info : ProjectExporter::getExporterTypes())
|
||||
{
|
||||
if (currentExporterName.contains (info.name))
|
||||
{
|
||||
saveAndOpenInIDEButton->iconImage = info.getIcon();
|
||||
saveAndOpenInIDEButton->repaint();
|
||||
saveAndOpenInIDEButton->setEnabled (canCurrentExporterLaunchProject());
|
||||
}
|
||||
}
|
||||
}
|
||||
//==========================================================================
|
||||
void buildPing();
|
||||
void buildFinished (bool);
|
||||
void setRunAppButtonState (bool);
|
||||
|
||||
void updateUserAvatar()
|
||||
{
|
||||
if (auto* controller = ProjucerApplication::getApp().licenseController.get())
|
||||
{
|
||||
auto state = controller->getState();
|
||||
//==========================================================================
|
||||
int tabsWidth = 200;
|
||||
bool isBuilding = false;
|
||||
|
||||
userSettingsButton->iconImage = state.avatar;
|
||||
userSettingsButton->repaint();
|
||||
}
|
||||
}
|
||||
Project* project = nullptr;
|
||||
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)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -478,7 +478,9 @@ void ProjectContentComponent::saveDocument()
|
|||
showSaveWarning (currentDocument);
|
||||
}
|
||||
else
|
||||
{
|
||||
saveProject();
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectContentComponent::saveAs()
|
||||
|
|
@ -521,11 +523,13 @@ bool ProjectContentComponent::goToCounterpart()
|
|||
return false;
|
||||
}
|
||||
|
||||
bool ProjectContentComponent::saveProject (bool shouldWait)
|
||||
bool ProjectContentComponent::saveProject (bool shouldWait, bool openInIDE)
|
||||
{
|
||||
if (project != nullptr)
|
||||
{
|
||||
const ScopedValueSetter<bool> valueSetter (project->shouldWaitAfterSaving, shouldWait, false);
|
||||
project->setOpenInIDEAfterSaving (openInIDE);
|
||||
|
||||
return (project->save (true, true) == FileBasedDocument::savedOk);
|
||||
}
|
||||
|
||||
|
|
@ -637,11 +641,16 @@ void ProjectContentComponent::openInSelectedIDE (bool saveFirst)
|
|||
{
|
||||
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;
|
||||
|
||||
exporter->launchProject();
|
||||
break;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1155,9 +1164,6 @@ void ProjectContentComponent::setBuildEnabled (bool isEnabled, bool displayError
|
|||
LiveBuildProjectSettings::setBuildDisabled (*project, ! isEnabled);
|
||||
killChildProcess();
|
||||
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);
|
||||
|
||||
if (auto* h = dynamic_cast<HeaderComponent*> (header.get()))
|
||||
h->updateBuildButtons (isBuildEnabled(), b);
|
||||
|
||||
getAppSettings().getGlobalProperties().setValue ("continuousRebuild", b);
|
||||
|
||||
ProjucerApplication::getCommandManager().commandStatusChanged();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ public:
|
|||
bool canGoToCounterpart() const;
|
||||
bool goToCounterpart();
|
||||
|
||||
bool saveProject (bool shouldWait = false);
|
||||
bool saveProject (bool shouldWait = false, bool openInIDE = false);
|
||||
void closeProject();
|
||||
void openInSelectedIDE (bool saveFirst);
|
||||
void showNewExporterMenu();
|
||||
|
|
|
|||
|
|
@ -394,6 +394,13 @@ static void registerRecentFile (const File& file)
|
|||
getAppSettings().flush();
|
||||
}
|
||||
|
||||
static void forgetRecentFile (const File& file)
|
||||
{
|
||||
RecentlyOpenedFilesList::forgetRecentFileNatively (file);
|
||||
getAppSettings().recentFiles.removeFile (file);
|
||||
getAppSettings().flush();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
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!");
|
||||
|
||||
registerRecentFile (file);
|
||||
|
||||
enabledModulesList.reset();
|
||||
projectRoot = newTree;
|
||||
|
||||
|
|
@ -437,9 +445,15 @@ Result Project::saveProject (const File& file, bool isCommandLineApp)
|
|||
if (isSaving)
|
||||
return Result::ok();
|
||||
|
||||
if (isTemporaryProject())
|
||||
{
|
||||
askUserWhereToSaveProject();
|
||||
return Result::ok();
|
||||
}
|
||||
|
||||
updateProjectSettings();
|
||||
|
||||
if (! isCommandLineApp)
|
||||
if (! isCommandLineApp && ! isTemporaryProject())
|
||||
registerRecentFile (file);
|
||||
|
||||
const ScopedValueSetter<bool> vs (isSaving, true, false);
|
||||
|
|
@ -454,17 +468,55 @@ Result Project::saveResourcesOnly (const File& file)
|
|||
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)
|
||||
{
|
||||
if (tree.getRoot() == tree)
|
||||
{
|
||||
if (property == Ids::projectType)
|
||||
{
|
||||
sendChangeMessage();
|
||||
}
|
||||
else if (property == Ids::name)
|
||||
{
|
||||
setTitle (projectRoot [Ids::name]);
|
||||
}
|
||||
else if (property == Ids::defines)
|
||||
{
|
||||
parsedPreprocessorDefs = parsePreprocessorDefs (preprocessorDefsValue.get());
|
||||
}
|
||||
|
||||
changed();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
class ProjectExporter;
|
||||
class LibraryModule;
|
||||
class EnabledModuleList;
|
||||
class ProjectContentComponent;
|
||||
|
||||
//==============================================================================
|
||||
class Project : public FileBasedDocument,
|
||||
|
|
@ -331,10 +332,18 @@ public:
|
|||
String getUniqueTargetFolderSuffixForExporter (const String& exporterName, const String& baseTargetFolder);
|
||||
|
||||
//==============================================================================
|
||||
bool isCurrentlySaving() const noexcept { return isSaving; }
|
||||
bool isCurrentlySaving() const noexcept { return isSaving; }
|
||||
bool shouldWaitAfterSaving = false;
|
||||
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:
|
||||
ValueTree projectRoot { Ids::JUCERPROJECT };
|
||||
|
||||
|
|
@ -349,6 +358,16 @@ private:
|
|||
pluginAUMainTypeValue, pluginRTASCategoryValue, pluginRTASBypassDisabledValue, pluginRTASMultiMonoDisabledValue,
|
||||
pluginAAXIdentifierValue, pluginAAXCategoryValue, pluginAAXBypassDisabledValue, pluginAAXMultiMonoDisabledValue;
|
||||
|
||||
//==============================================================================
|
||||
File tempDirectory = {};
|
||||
bool openInIDEAfterSaving = false;
|
||||
|
||||
void askUserWhereToSaveProject();
|
||||
void moveTemporaryDirectory (const File&);
|
||||
|
||||
//==============================================================================
|
||||
bool hasSentGUIBuilderAnalyticsEvent = false;
|
||||
|
||||
//==============================================================================
|
||||
friend class Item;
|
||||
ScopedPointer<EnabledModuleList> enabledModulesList;
|
||||
|
|
|
|||
|
|
@ -138,6 +138,32 @@ public:
|
|||
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)
|
||||
{
|
||||
if (! generatedCodeFolder.createDirectory())
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
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,
|
||||
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,
|
||||
|
|
@ -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,
|
||||
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,
|
||||
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 };
|
||||
|
|
@ -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,
|
||||
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,
|
||||
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 (config)
|
||||
JUCE_LOAD_PATH_DATA (graph)
|
||||
// JUCE_LOAD_PATH_DATA (exporter)
|
||||
JUCE_LOAD_PATH_DATA (jigsaw)
|
||||
JUCE_LOAD_PATH_DATA (info)
|
||||
JUCE_LOAD_PATH_DATA (warning)
|
||||
JUCE_LOAD_PATH_DATA (bug)
|
||||
// JUCE_LOAD_PATH_DATA (play)
|
||||
JUCE_LOAD_PATH_DATA (code)
|
||||
JUCE_LOAD_PATH_DATA (box)
|
||||
JUCE_LOAD_PATH_DATA (juceLogo)
|
||||
JUCE_LOAD_PATH_DATA (mainJuceLogo)
|
||||
|
||||
JUCE_LOAD_PATH_DATA (user)
|
||||
JUCE_LOAD_PATH_DATA (closedFolder)
|
||||
JUCE_LOAD_PATH_DATA (exporter)
|
||||
|
|
@ -1610,9 +1579,6 @@ Icons::Icons()
|
|||
JUCE_LOAD_PATH_DATA (play)
|
||||
JUCE_LOAD_PATH_DATA (settings)
|
||||
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 (plus);
|
||||
JUCE_LOAD_PATH_DATA (android);
|
||||
|
|
|
|||
|
|
@ -72,16 +72,10 @@ class Icons
|
|||
public:
|
||||
Icons();
|
||||
|
||||
Path folder, document, imageDoc,
|
||||
config, /*exporter,*/ juceLogo,
|
||||
graph, jigsaw, info, warning,
|
||||
bug, /*play,*/ code, box,
|
||||
mainJuceLogo;
|
||||
|
||||
Path user, closedFolder, exporter, fileExplorer, file,
|
||||
buildTab, modules, openFolder, play, settings, singleModule,
|
||||
buildNow, continuousBuildStart, continuousBuildStop, edit, plus,
|
||||
android, codeBlocks, linux, xcode, visualStudio, clion;
|
||||
Path folder, document, imageDoc, config, juceLogo, graph, jigsaw, info, warning, bug,
|
||||
code, box, mainJuceLogo, user, closedFolder, exporter, fileExplorer, file, buildTab,
|
||||
modules, openFolder, play, settings, singleModule, edit, plus, android, codeBlocks,
|
||||
linux, xcode, visualStudio, clion;
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Icons)
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../../Licenses/jucer_LicenseController.h"
|
||||
#include "../../Application/jucer_Application.h"
|
||||
|
||||
//==============================================================================
|
||||
class UserSettingsPopup : public Component
|
||||
|
|
|
|||
|
|
@ -158,13 +158,15 @@ public:
|
|||
// Handle Open Project button functionality
|
||||
ApplicationCommandManager& commandManager = ProjucerApplication::getCommandManager();
|
||||
|
||||
addAndMakeVisible (blankProjectButton = new TemplateOptionButton ("Create Blank Project", TemplateOptionButton::ImageOnButtonBackground, BinaryData::wizard_Openfile_svg));
|
||||
addAndMakeVisible (exampleProjectButton = new TemplateOptionButton ("Open Example Project", TemplateOptionButton::ImageOnButtonBackground, BinaryData::wizard_Openfile_svg));
|
||||
addAndMakeVisible (openProjectButton = new TemplateOptionButton ("Open Existing Project", TemplateOptionButton::ImageOnButtonBackground, BinaryData::wizard_Openfile_svg));
|
||||
addAndMakeVisible (blankProjectButton);
|
||||
addAndMakeVisible (openProjectButton);
|
||||
addAndMakeVisible (browseDemosButton);
|
||||
addAndMakeVisible (viewTutorialsButton);
|
||||
|
||||
blankProjectButton->onClick = [this] { createBlankProject(); };
|
||||
exampleProjectButton->onClick = [this] { openExampleProject(); };
|
||||
openProjectButton->setCommandToTrigger (&commandManager, CommandIDs::open, true);
|
||||
blankProjectButton.onClick = [this] { createBlankProject(); };
|
||||
openProjectButton.setCommandToTrigger (&commandManager, CommandIDs::open, true);
|
||||
browseDemosButton.setCommandToTrigger (&commandManager, CommandIDs::launchDemoRunner, true);
|
||||
viewTutorialsButton.setCommandToTrigger (&commandManager, CommandIDs::showTutorials, true);
|
||||
|
||||
newProjectWizard = projectWizard;
|
||||
}
|
||||
|
|
@ -185,35 +187,41 @@ public:
|
|||
|
||||
for (int i = 0; i < optionButtons.size(); ++i)
|
||||
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
|
||||
{
|
||||
auto allOpts = getLocalBounds().reduced (40, 60);
|
||||
allOpts.removeFromBottom (allOpts.getHeight() / 4);
|
||||
auto bounds = getLocalBounds().reduced (40, 0);
|
||||
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,
|
||||
allOpts.getY() + yShift * allOpts.getHeight() / 2,
|
||||
optStep, allOpts.getHeight() / 2)
|
||||
.reduced (10, 10));
|
||||
auto topSlice = optionBounds.removeFromTop (optionBounds.getHeight() / 2).reduced (0, 10);
|
||||
auto bottomSlice = optionBounds.reduced (0, 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();
|
||||
openButtonBounds.removeFromBottom (proportionOfHeight (0.12f));
|
||||
openButtonBounds = openButtonBounds.removeFromBottom (120);
|
||||
openButtonBounds.reduce (50, 40);
|
||||
bounds.removeFromTop (20);
|
||||
auto topButtonBounds = bounds.removeFromTop (50);
|
||||
|
||||
blankProjectButton->setBounds (openButtonBounds.removeFromLeft (optStep - 20));
|
||||
exampleProjectButton->setBounds (openButtonBounds.removeFromRight (optStep - 20));
|
||||
openProjectButton->setBounds (openButtonBounds.reduced (18, 0));
|
||||
openProjectButton.setBounds (topButtonBounds.reduced (80, 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)
|
||||
|
|
@ -231,36 +239,14 @@ public:
|
|||
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:
|
||||
OwnedArray<TemplateOptionButton> optionButtons;
|
||||
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)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue