1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-11 23:54:18 +00:00

Projucer: Removed the live build

This commit is contained in:
Tom Poole 2021-05-14 08:18:19 +01:00
parent 64896eefcd
commit bfdda737a2
74 changed files with 673 additions and 7583 deletions

View file

@ -25,17 +25,14 @@
#include "../../Application/jucer_Headers.h"
#include "jucer_ProjectContentComponent.h"
#include "../../LiveBuildEngine/jucer_DownloadCompileEngineThread.h"
#include "../../LiveBuildEngine/jucer_CompileEngineSettings.h"
#include "Sidebar/jucer_TabComponents.h"
#include "Sidebar/jucer_ProjectTab.h"
#include "Sidebar/jucer_LiveBuildTab.h"
#include "Sidebar/jucer_Sidebar.h"
NewFileWizard::Type* createGUIComponentWizard();
//==============================================================================
ProjectContentComponent::ProjectContentComponent()
: sidebar (new Sidebar (project))
{
setOpaque (true);
setWantsKeyboardFocus (true);
@ -47,25 +44,13 @@ ProjectContentComponent::ProjectContentComponent()
sidebarSizeConstrainer.setMinimumWidth (200);
sidebarSizeConstrainer.setMaximumWidth (500);
sidebarTabs.setOutline (0);
sidebarTabs.getTabbedButtonBar().setMinimumTabScaleFactor (0.5);
sidebarTabs.setTitle ("Sidebar");
sidebarTabs.setFocusContainerType (FocusContainerType::focusContainer);
ProjucerApplication::getApp().openDocumentManager.addListener (this);
isLiveBuildEnabled = getGlobalProperties().getBoolValue (Ids::liveBuildEnabled);
getGlobalProperties().addChangeListener (this);
liveBuildEnablementChanged (isLiveBuildEnabled);
Desktop::getInstance().addFocusChangeListener (this);
}
ProjectContentComponent::~ProjectContentComponent()
{
Desktop::getInstance().removeFocusChangeListener (this);
killChildProcess();
getGlobalProperties().removeChangeListener (this);
ProjucerApplication::getApp().openDocumentManager.removeListener (this);
@ -91,18 +76,18 @@ void ProjectContentComponent::resized()
r.removeFromTop (10);
auto sidebarArea = r.removeFromLeft (sidebarTabs.getWidth() != 0 ? sidebarTabs.getWidth()
: r.getWidth() / 4);
auto sidebarArea = r.removeFromLeft (sidebar->getWidth() != 0 ? sidebar->getWidth()
: r.getWidth() / 4);
if (sidebarTabs.isVisible())
sidebarTabs.setBounds (sidebarArea);
if (sidebar->isVisible())
sidebar->setBounds (sidebarArea);
if (resizerBar != nullptr)
resizerBar->setBounds (r.withWidth (4));
contentViewComponent.setBounds (r);
headerComponent.sidebarTabsWidthChanged (sidebarTabs.getWidth());
headerComponent.sidebarTabsWidthChanged (sidebar->getWidth());
}
void ProjectContentComponent::lookAndFeelChanged()
@ -115,7 +100,7 @@ void ProjectContentComponent::lookAndFeelChanged()
void ProjectContentComponent::childBoundsChanged (Component* child)
{
if (child == &sidebarTabs)
if (child == sidebar.get())
resized();
}
@ -123,135 +108,47 @@ void ProjectContentComponent::setProject (Project* newProject)
{
if (project != newProject)
{
lastCrashMessage = {};
killChildProcess();
if (project != nullptr)
project->removeChangeListener (this);
hideEditor();
resizerBar = nullptr;
deleteProjectTabs();
project = newProject;
rebuildProjectUI();
}
}
//==============================================================================
static LiveBuildTab* findBuildTab (const TabbedComponent& tabs)
{
return dynamic_cast<LiveBuildTab*> (tabs.getTabContentComponent (1));
}
bool ProjectContentComponent::isBuildTabEnabled() const
{
auto bt = findBuildTab (sidebarTabs);
return bt != nullptr && bt->isEnabled;
}
void ProjectContentComponent::createProjectTabs()
{
jassert (project != nullptr);
auto tabColour = Colours::transparentBlack;
sidebarTabs.addTab (getProjectTabName(), tabColour, new ProjectTab (project), true);
if (isLiveBuildEnabled)
{
CompileEngineChildProcess::Ptr childProc (getChildProcess());
sidebarTabs.addTab (getBuildTabName(), tabColour, new LiveBuildTab (childProc, lastCrashMessage), true);
if (childProc != nullptr)
if (project != nullptr)
{
childProc->crashHandler = [this] (const String& m) { this->handleCrash (m); };
sidebar = std::make_unique<Sidebar> (project);
addAndMakeVisible (sidebar.get());
sidebarTabs.getTabbedButtonBar().getTabButton (1)->setExtraComponent (new BuildStatusTabComp (childProc->errorList,
childProc->activityList),
TabBarButton::afterText);
//==============================================================================
resizerBar.reset (new ResizableEdgeComponent (sidebar.get(), &sidebarSizeConstrainer,
ResizableEdgeComponent::rightEdge));
addAndMakeVisible (resizerBar.get());
resizerBar->setAlwaysOnTop (true);
project->addChangeListener (this);
updateMissingFileStatuses();
headerComponent.setVisible (true);
headerComponent.setCurrentProject (project);
projectMessagesComponent.setVisible (true);
}
else
{
sidebar->setVisible (false);
headerComponent.setVisible (false);
projectMessagesComponent.setVisible (false);
}
projectMessagesComponent.setProject (project);
resized();
}
}
void ProjectContentComponent::deleteProjectTabs()
{
if (project != nullptr && sidebarTabs.getNumTabs() > 0)
{
auto& settings = project->getStoredProperties();
if (sidebarTabs.getWidth() > 0)
settings.setValue ("projectPanelWidth", sidebarTabs.getWidth());
settings.setValue ("lastViewedTabIndex", sidebarTabs.getCurrentTabIndex());
for (int i = 0; i < 3; ++i)
settings.setValue ("projectTabPanelHeight" + String (i),
getProjectTab()->getPanelHeightProportion (i));
}
sidebarTabs.clearTabs();
}
void ProjectContentComponent::rebuildProjectUI()
{
deleteProjectTabs();
if (project != nullptr)
{
addAndMakeVisible (sidebarTabs);
createProjectTabs();
//==============================================================================
auto& settings = project->getStoredProperties();
auto lastTreeWidth = settings.getValue ("projectPanelWidth").getIntValue();
if (lastTreeWidth < 150)
lastTreeWidth = 240;
sidebarTabs.setBounds (0, 0, lastTreeWidth, getHeight());
auto lastTabIndex = settings.getValue ("lastViewedTabIndex", "0").getIntValue();
if (lastTabIndex >= sidebarTabs.getNumTabs())
lastTabIndex = 0;
sidebarTabs.setCurrentTabIndex (lastTabIndex);
auto* projectTab = getProjectTab();
for (int i = 2; i >= 0; --i)
projectTab->setPanelHeightProportion (i, settings.getValue ("projectTabPanelHeight" + String (i), "1")
.getFloatValue());
//==============================================================================
resizerBar.reset (new ResizableEdgeComponent (&sidebarTabs, &sidebarSizeConstrainer,
ResizableEdgeComponent::rightEdge));
addAndMakeVisible (resizerBar.get());
resizerBar->setAlwaysOnTop (true);
project->addChangeListener (this);
updateMissingFileStatuses();
headerComponent.setVisible (true);
headerComponent.setCurrentProject (project);
projectMessagesComponent.setVisible (true);
}
else
{
sidebarTabs.setVisible (false);
headerComponent.setVisible (false);
projectMessagesComponent.setVisible (false);
}
projectMessagesComponent.setProject (project);
resized();
}
void ProjectContentComponent::saveTreeViewState()
{
}
@ -288,30 +185,19 @@ bool ProjectContentComponent::documentAboutToClose (OpenDocumentManager::Documen
void ProjectContentComponent::changeListenerCallback (ChangeBroadcaster* broadcaster)
{
if (broadcaster == project)
{
updateMissingFileStatuses();
}
else if (broadcaster == &getGlobalProperties())
{
auto isEnabled = ProjucerApplication::getApp().isLiveBuildEnabled();
if (isLiveBuildEnabled != isEnabled)
liveBuildEnablementChanged (isEnabled);
}
}
void ProjectContentComponent::refreshProjectTreeFileStatuses()
{
if (auto* projectTab = getProjectTab())
if (auto* fileTree = projectTab->getFileTreePanel())
fileTree->repaint();
if (auto* fileTree = sidebar->getFileTreePanel())
fileTree->repaint();
}
void ProjectContentComponent::updateMissingFileStatuses()
{
if (auto* pTab = getProjectTab())
if (auto* tree = pTab->getFileTreePanel())
tree->updateMissingFileStatuses();
if (auto* tree = sidebar->getFileTreePanel())
tree->updateMissingFileStatuses();
}
bool ProjectContentComponent::showEditorForFile (const File& fileToShow, bool grabFocus)
@ -529,7 +415,7 @@ void ProjectContentComponent::showExporterSettings (const String& exporterName)
showExportersPanel();
if (auto* exportersPanel = getProjectTab()->getExportersTreePanel())
if (auto* exportersPanel = sidebar->getExportersTreePanel())
{
if (auto* exporters = dynamic_cast<TreeItemTypes::ExportersTreeRoot*> (exportersPanel->rootItem.get()))
{
@ -554,7 +440,7 @@ void ProjectContentComponent::showModule (const String& moduleID)
{
showModulesPanel();
if (auto* modsPanel = getProjectTab()->getModuleTreePanel())
if (auto* modsPanel = sidebar->getModuleTreePanel())
{
if (auto* mods = dynamic_cast<TreeItemTypes::EnabledModulesItem*> (modsPanel->rootItem.get()))
{
@ -575,11 +461,6 @@ void ProjectContentComponent::showModule (const String& moduleID)
}
}
void ProjectContentComponent::showLiveBuildSettings()
{
setScrollableEditorComponent (std::make_unique<LiveBuildSettingsComponent> (*project));
}
StringArray ProjectContentComponent::getExportersWhichCanLaunch() const
{
StringArray s;
@ -640,7 +521,7 @@ void ProjectContentComponent::showNewExporterMenu()
void ProjectContentComponent::deleteSelectedTreeItems()
{
if (auto* tree = getProjectTab()->getTreeWithSelectedItems())
if (auto* tree = sidebar->getTreeWithSelectedItems())
tree->deleteSelectedItems();
}
@ -721,8 +602,6 @@ void ProjectContentComponent::getAllCommands (Array <CommandID>& commands)
CommandIDs::goToNextDoc,
CommandIDs::goToCounterpart,
CommandIDs::showProjectSettings,
CommandIDs::showProjectTab,
CommandIDs::showBuildTab,
CommandIDs::showFileExplorerPanel,
CommandIDs::showModulesPanel,
CommandIDs::showExportersPanel,
@ -732,16 +611,6 @@ void ProjectContentComponent::getAllCommands (Array <CommandID>& commands)
CommandIDs::createNewExporter,
CommandIDs::deleteSelectedItem,
CommandIDs::showTranslationTool,
CommandIDs::cleanAll,
CommandIDs::toggleBuildEnabled,
CommandIDs::buildNow,
CommandIDs::toggleContinuousBuild,
CommandIDs::launchApp,
CommandIDs::killApp,
CommandIDs::reinstantiateComp,
CommandIDs::showWarnings,
CommandIDs::nextError,
CommandIDs::prevError,
CommandIDs::addNewGUIFile });
}
@ -830,22 +699,6 @@ void ProjectContentComponent::getCommandInfo (const CommandID commandID, Applica
result.defaultKeypresses.add ({ 'x', cmdCtrl, 0 });
break;
case CommandIDs::showProjectTab:
result.setInfo ("Show Project Tab",
"Shows the tab containing the project information",
CommandCategories::general, 0);
result.setActive (project != nullptr);
result.defaultKeypresses.add ({ 'p', cmdCtrl, 0 });
break;
case CommandIDs::showBuildTab:
result.setInfo ("Show Build Tab",
"Shows the tab containing the build panel",
CommandCategories::general, 0);
result.setActive (project != nullptr && isLiveBuildEnabled);
result.defaultKeypresses.add ({ 'b', cmdCtrl, 0 });
break;
case CommandIDs::showFileExplorerPanel:
result.setInfo ("Show File Explorer Panel",
"Shows the panel containing the tree of files for this project",
@ -906,7 +759,6 @@ void ProjectContentComponent::getCommandInfo (const CommandID commandID, Applica
CommandCategories::general, 0);
result.defaultKeypresses.add ({ KeyPress::deleteKey, 0, 0 });
result.defaultKeypresses.add ({ KeyPress::backspaceKey, 0, 0 });
result.setActive (sidebarTabs.getCurrentTabIndex() == 0);
break;
case CommandIDs::showTranslationTool:
@ -915,87 +767,6 @@ void ProjectContentComponent::getCommandInfo (const CommandID commandID, Applica
CommandCategories::general, 0);
break;
case CommandIDs::cleanAll:
result.setInfo ("Clean All",
"Cleans all intermediate files",
CommandCategories::general, 0);
result.defaultKeypresses.add ({ 'k', ModifierKeys::commandModifier | ModifierKeys::shiftModifier, 0 });
result.setActive (project != nullptr);
break;
case CommandIDs::toggleBuildEnabled:
result.setInfo ("Enable Compilation",
"Enables/disables the compiler",
CommandCategories::general, 0);
result.defaultKeypresses.add ({ 'b', ModifierKeys::commandModifier | ModifierKeys::shiftModifier, 0 });
result.setActive (project != nullptr);
result.setTicked (childProcess != nullptr);
break;
case CommandIDs::buildNow:
result.setInfo ("Build Now",
"Recompiles any out-of-date files and updates the JIT engine",
CommandCategories::general, 0);
result.defaultKeypresses.add ({ 'b', ModifierKeys::commandModifier, 0 });
result.setActive (childProcess != nullptr);
break;
case CommandIDs::toggleContinuousBuild:
result.setInfo ("Enable Continuous Recompiling",
"Continuously recompiles any changes made in code editors",
CommandCategories::general, 0);
result.setActive (childProcess != nullptr);
result.setTicked (isContinuousRebuildEnabled());
break;
case CommandIDs::launchApp:
result.setInfo ("Launch Application",
"Invokes the app's main() function",
CommandCategories::general, 0);
result.defaultKeypresses.add ({ 'r', ModifierKeys::commandModifier, 0 });
result.setActive (childProcess != nullptr && childProcess->canLaunchApp());
break;
case CommandIDs::killApp:
result.setInfo ("Stop Application",
"Kills the app if it's running",
CommandCategories::general, 0);
result.defaultKeypresses.add ({ '.', ModifierKeys::commandModifier, 0 });
result.setActive (childProcess != nullptr && childProcess->canKillApp());
break;
case CommandIDs::reinstantiateComp:
result.setInfo ("Re-instantiate Components",
"Re-loads any component editors that are open",
CommandCategories::general, 0);
result.defaultKeypresses.add ({ 'r', ModifierKeys::commandModifier | ModifierKeys::shiftModifier, 0 });
result.setActive (childProcess != nullptr);
break;
case CommandIDs::showWarnings:
result.setInfo ("Show Warnings",
"Shows or hides compilation warnings",
CommandCategories::general, 0);
result.setActive (project != nullptr);
result.setTicked (areWarningsEnabled());
break;
case CommandIDs::nextError:
result.setInfo ("Highlight next error",
"Jumps to the next error or warning",
CommandCategories::general, 0);
result.defaultKeypresses.add ({ '\'', ModifierKeys::commandModifier, 0 });
result.setActive (childProcess != nullptr && ! childProcess->errorList.isEmpty());
break;
case CommandIDs::prevError:
result.setInfo ("Highlight previous error",
"Jumps to the last error or warning",
CommandCategories::general, 0);
result.defaultKeypresses.add ({ '\"', ModifierKeys::commandModifier, 0 });
result.setActive (childProcess != nullptr && ! childProcess->errorList.isEmpty());
break;
case CommandIDs::addNewGUIFile:
result.setInfo ("Add new GUI Component...",
"Adds a new GUI Component file to the project",
@ -1052,8 +823,6 @@ bool ProjectContentComponent::perform (const InvocationInfo& info)
case CommandIDs::goToCounterpart: goToCounterpart(); break;
case CommandIDs::showProjectSettings: showProjectSettings(); break;
case CommandIDs::showProjectTab: showProjectTab(); break;
case CommandIDs::showBuildTab: showBuildTab(); break;
case CommandIDs::showFileExplorerPanel: showFilesPanel(); break;
case CommandIDs::showModulesPanel: showModulesPanel(); break;
case CommandIDs::showExportersPanel: showExportersPanel(); break;
@ -1068,17 +837,6 @@ bool ProjectContentComponent::perform (const InvocationInfo& info)
case CommandIDs::showTranslationTool: showTranslationTool(); break;
case CommandIDs::cleanAll: cleanAll(); break;
case CommandIDs::toggleBuildEnabled: setBuildEnabled (! isBuildEnabled()); break;
case CommandIDs::buildNow: rebuildNow(); break;
case CommandIDs::toggleContinuousBuild: setContinuousRebuildEnabled (! isContinuousRebuildEnabled()); break;
case CommandIDs::launchApp: launchApp(); break;
case CommandIDs::killApp: killApp(); break;
case CommandIDs::reinstantiateComp: reinstantiateLivePreviewWindows(); break;
case CommandIDs::showWarnings: toggleWarnings(); break;
case CommandIDs::nextError: showNextError(); break;
case CommandIDs::prevError: showPreviousError(); break;
case CommandIDs::addNewGUIFile: addNewGUIFile(); break;
default:
@ -1099,122 +857,6 @@ void ProjectContentComponent::getSelectedProjectItemsBeingDragged (const DragAnd
TreeItemTypes::FileTreeItemBase::getSelectedProjectItemsBeingDragged (dragSourceDetails, selectedNodes);
}
//==============================================================================
void ProjectContentComponent::killChildProcess()
{
if (childProcess != nullptr)
{
deleteProjectTabs();
childProcess = nullptr;
ProjucerApplication::getApp().childProcessCache->removeOrphans();
}
}
void ProjectContentComponent::setBuildEnabled (bool isEnabled, bool displayError)
{
if (project != nullptr && isEnabled != isBuildEnabled())
{
if (! displayError)
lastCrashMessage = {};
project->getCompileEngineSettings().setBuildEnabled (isEnabled);
killChildProcess();
refreshTabsIfBuildStatusChanged();
}
}
void ProjectContentComponent::cleanAll()
{
lastCrashMessage = {};
if (childProcess != nullptr)
childProcess->cleanAll();
else if (auto* p = getProject())
CompileEngineChildProcess::cleanAllCachedFilesForProject (*p);
}
void ProjectContentComponent::handleCrash (const String& message)
{
lastCrashMessage = message.isEmpty() ? TRANS("JIT process stopped responding!")
: (TRANS("JIT process crashed!") + ":\n\n" + message);
if (project != nullptr)
{
setBuildEnabled (false, true);
showBuildTab();
}
}
bool ProjectContentComponent::isBuildEnabled() const
{
return isLiveBuildEnabled
&& project != nullptr
&& project->getCompileEngineSettings().isBuildEnabled()
&& CompileEngineDLL::getInstance()->isLoaded();
}
void ProjectContentComponent::refreshTabsIfBuildStatusChanged()
{
if (project != nullptr
&& isLiveBuildEnabled
&& (sidebarTabs.getNumTabs() < 2 || isBuildEnabled() != isBuildTabEnabled()))
{
rebuildProjectUI();
}
}
bool ProjectContentComponent::areWarningsEnabled() const
{
return project != nullptr && project->getCompileEngineSettings().areWarningsEnabled();
}
void ProjectContentComponent::updateWarningState()
{
if (childProcess != nullptr)
childProcess->errorList.setWarningsEnabled (areWarningsEnabled());
}
void ProjectContentComponent::toggleWarnings()
{
if (project != nullptr)
{
project->getCompileEngineSettings().setWarningsEnabled (! areWarningsEnabled());
updateWarningState();
}
}
static ProjucerAppClasses::ErrorListComp* findErrorListComp (const TabbedComponent& tabs)
{
if (auto* bt = findBuildTab (tabs))
return bt->errorListComp;
return nullptr;
}
void ProjectContentComponent::showNextError()
{
if (auto* el = findErrorListComp (sidebarTabs))
{
showBuildTab();
el->showNext();
}
}
void ProjectContentComponent::showPreviousError()
{
if (auto* el = findErrorListComp (sidebarTabs))
{
showBuildTab();
el->showPrevious();
}
}
void ProjectContentComponent::reinstantiateLivePreviewWindows()
{
if (childProcess != nullptr)
childProcess->reinstantiatePreviews();
}
void ProjectContentComponent::addNewGUIFile()
{
if (project != nullptr)
@ -1224,131 +866,8 @@ void ProjectContentComponent::addNewGUIFile()
}
}
void ProjectContentComponent::launchApp()
{
if (childProcess != nullptr)
childProcess->launchApp();
}
void ProjectContentComponent::killApp()
{
if (childProcess != nullptr)
childProcess->killApp();
}
void ProjectContentComponent::rebuildNow()
{
if (childProcess != nullptr)
childProcess->flushEditorChanges();
}
void ProjectContentComponent::globalFocusChanged (Component* focusedComponent)
{
auto nowForeground = (Process::isForegroundProcess()
&& (focusedComponent == this || isParentOf (focusedComponent)));
if (nowForeground != isForeground)
{
isForeground = nowForeground;
if (childProcess != nullptr)
childProcess->processActivationChanged (isForeground);
}
}
void ProjectContentComponent::timerCallback()
{
if (! isBuildEnabled())
killChildProcess();
refreshTabsIfBuildStatusChanged();
}
void ProjectContentComponent::liveBuildEnablementChanged (bool isEnabled)
{
isLiveBuildEnabled = isEnabled;
if (isLiveBuildEnabled)
{
startTimer (1600);
}
else
{
stopTimer();
killChildProcess();
}
rebuildProjectUI();
headerComponent.liveBuildEnablementChanged (isLiveBuildEnabled);
}
bool ProjectContentComponent::isContinuousRebuildEnabled()
{
return project != nullptr && project->getCompileEngineSettings().isContinuousRebuildEnabled();
}
void ProjectContentComponent::setContinuousRebuildEnabled (bool b)
{
if (project != nullptr && childProcess != nullptr)
{
project->getCompileEngineSettings().setContinuousRebuildEnabled (b);
ProjucerApplication::getCommandManager().commandStatusChanged();
}
}
ReferenceCountedObjectPtr<CompileEngineChildProcess> ProjectContentComponent::getChildProcess()
{
if (childProcess == nullptr && isBuildEnabled())
childProcess = ProjucerApplication::getApp().childProcessCache->getOrCreate (*project);
return childProcess;
}
void ProjectContentComponent::handleMissingSystemHeaders()
{
#if JUCE_MAC
String tabMessage ("Compiler not available due to missing system headers\nPlease install a recent version of Xcode");
String alertWindowMessage ("Missing system headers\nPlease install a recent version of Xcode");
#elif JUCE_WINDOWS
String tabMessage ("Compiler not available due to missing system headers\nPlease install a recent version of Visual Studio and the Windows Desktop SDK");
String alertWindowMessage ("Missing system headers\nPlease install a recent version of Visual Studio and the Windows Desktop SDK");
#elif JUCE_LINUX || JUCE_BSD
String tabMessage ("Compiler not available due to missing system headers\nPlease install using your package manager");
String alertWindowMessage ("Missing system headers\nPlease install using your package manager");
#endif
setBuildEnabled (false, true);
deleteProjectTabs();
createProjectTabs();
if (auto* bt = getLiveBuildTab())
{
bt->isEnabled = false;
bt->errorMessage = tabMessage;
}
showBuildTab();
AlertWindow::showMessageBox (AlertWindow::AlertIconType::WarningIcon,
"Missing system headers", alertWindowMessage);
}
//==============================================================================
void ProjectContentComponent::showProjectPanel (const int index)
{
showProjectTab();
if (auto* pTab = getProjectTab())
pTab->showPanel (index);
}
ProjectTab* ProjectContentComponent::getProjectTab()
{
return dynamic_cast<ProjectTab*> (sidebarTabs.getTabContentComponent (0));
}
LiveBuildTab* ProjectContentComponent::getLiveBuildTab()
{
return dynamic_cast<LiveBuildTab*> (sidebarTabs.getTabContentComponent (1));
sidebar->showPanel (index);
}