| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library.
 -    Copyright (c) 2015 - ROLI Ltd.
 - 
 -    Permission is granted to use this software under the terms of either:
 -    a) the GPL v2 (or any later version)
 -    b) the Affero GPL v3
 - 
 -    Details of these licenses can be found at: www.gnu.org/licenses
 - 
 -    JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
 -    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 -    A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 - 
 -    ------------------------------------------------------------------------------
 - 
 -    To release a closed-source product which uses JUCE, commercial licenses are
 -    available: visit www.juce.com for more information.
 - 
 -   ==============================================================================
 - */
 - 
 - #include "../jucer_Headers.h"
 - #include "jucer_ProjectContentComponent.h"
 - #include "jucer_Module.h"
 - #include "../Application/jucer_MainWindow.h"
 - #include "../Application/jucer_Application.h"
 - #include "../Code Editor/jucer_SourceCodeEditor.h"
 - #include "../Utility/jucer_FilePathPropertyComponent.h"
 - #include "jucer_TreeItemTypes.h"
 - 
 - 
 - //==============================================================================
 - class FileTreePanel   : public TreePanelBase
 - {
 - public:
 -     FileTreePanel (Project& p)
 -         : TreePanelBase (&p, "fileTreeState")
 -     {
 -         tree.setMultiSelectEnabled (true);
 -         setRoot (new FileTreeItemTypes::GroupItem (p.getMainGroup()));
 -     }
 - 
 -     void updateMissingFileStatuses()
 -     {
 -         if (FileTreeItemTypes::ProjectTreeItemBase* p = dynamic_cast<FileTreeItemTypes::ProjectTreeItemBase*> (rootItem.get()))
 -             p->checkFileStatus();
 -     }
 - };
 - 
 - //==============================================================================
 - class ConfigTreePanel   : public TreePanelBase
 - {
 - public:
 -     ConfigTreePanel (Project& p)
 -         : TreePanelBase (&p, "settingsTreeState")
 -     {
 -         tree.setMultiSelectEnabled (false);
 -         setRoot (new ConfigTreeItemTypes::RootItem (p));
 - 
 -         if (tree.getNumSelectedItems() == 0)
 -             tree.getRootItem()->setSelected (true, true);
 - 
 -        #if JUCE_MAC || JUCE_WINDOWS
 -         ApplicationCommandManager& commandManager = ProjucerApplication::getCommandManager();
 - 
 -         addAndMakeVisible (createExporterButton);
 -         createExporterButton.setCommandToTrigger (&commandManager, CommandIDs::createNewExporter, true);
 -         createExporterButton.setButtonText (commandManager.getNameOfCommand (CommandIDs::createNewExporter));
 -         createExporterButton.setColour (TextButton::buttonColourId, Colours::white.withAlpha (0.5f));
 - 
 -         addAndMakeVisible (openProjectButton);
 -         openProjectButton.setCommandToTrigger (&commandManager, CommandIDs::openInIDE, true);
 -         openProjectButton.setButtonText (commandManager.getNameOfCommand (CommandIDs::openInIDE));
 -         openProjectButton.setColour (TextButton::buttonColourId, Colours::white.withAlpha (0.5f));
 - 
 -         addAndMakeVisible (saveAndOpenButton);
 -         saveAndOpenButton.setCommandToTrigger (&commandManager, CommandIDs::saveAndOpenInIDE, true);
 -         saveAndOpenButton.setButtonText (commandManager.getNameOfCommand (CommandIDs::saveAndOpenInIDE));
 -         saveAndOpenButton.setColour (TextButton::buttonColourId, Colours::white.withAlpha (0.5f));
 -        #endif
 -     }
 - 
 -     void resized() override
 -     {
 -         Rectangle<int> r (getAvailableBounds());
 -         r.removeFromBottom (6);
 - 
 -         if (saveAndOpenButton.isVisible())
 -             saveAndOpenButton.setBounds (r.removeFromBottom (30).reduced (16, 4));
 - 
 -         if (openProjectButton.isVisible())
 -             openProjectButton.setBounds (r.removeFromBottom (30).reduced (16, 4));
 - 
 -         if (createExporterButton.isVisible())
 -         {
 -             r.removeFromBottom (10);
 -             createExporterButton.setBounds (r.removeFromBottom (30).reduced (16, 4));
 -         }
 - 
 -         tree.setBounds (r);
 -     }
 - 
 -     static void reselect (TreeViewItem& item)
 -     {
 -         item.setSelected (false, true);
 -         item.setSelected (true, true);
 -     }
 - 
 -     void showProjectSettings()
 -     {
 -         if (ConfigTreeItemTypes::ConfigTreeItemBase* root = dynamic_cast<ConfigTreeItemTypes::ConfigTreeItemBase*> (rootItem.get()))
 -             if (root->isProjectSettings())
 -                 reselect (*root);
 -     }
 - 
 -     void showModules()
 -     {
 -         if (ConfigTreeItemTypes::ConfigTreeItemBase* mods = getModulesItem())
 -             reselect (*mods);
 -     }
 - 
 -     void showModule (const String& moduleID)
 -     {
 -         if (ConfigTreeItemTypes::ConfigTreeItemBase* mods = getModulesItem())
 -         {
 -             mods->setOpen (true);
 - 
 -             for (int i = mods->getNumSubItems(); --i >= 0;)
 -                 if (ConfigTreeItemTypes::ModuleItem* m = dynamic_cast<ConfigTreeItemTypes::ModuleItem*> (mods->getSubItem (i)))
 -                     if (m->moduleID == moduleID)
 -                         reselect (*m);
 -         }
 -     }
 - 
 -     TextButton createExporterButton, openProjectButton, saveAndOpenButton;
 - 
 - private:
 -     ConfigTreeItemTypes::ConfigTreeItemBase* getModulesItem()
 -     {
 -         if (ConfigTreeItemTypes::ConfigTreeItemBase* root = dynamic_cast<ConfigTreeItemTypes::ConfigTreeItemBase*> (rootItem.get()))
 -             if (root->isProjectSettings())
 -                 if (ConfigTreeItemTypes::ConfigTreeItemBase* mods = dynamic_cast<ConfigTreeItemTypes::ConfigTreeItemBase*> (root->getSubItem (0)))
 -                     if (mods->isModulesList())
 -                         return mods;
 - 
 -         return nullptr;
 -     }
 - };
 - 
 - //==============================================================================
 - struct LogoComponent  : public Component
 - {
 -     LogoComponent()
 -     {
 -         ScopedPointer<XmlElement> svg (XmlDocument::parse (BinaryData::background_logo_svg));
 -         logo = Drawable::createFromSVG (*svg);
 -     }
 - 
 -     void paint (Graphics& g) override
 -     {
 -         g.setColour (findColour (mainBackgroundColourId).contrasting (0.3f));
 - 
 -         Rectangle<int> r (getLocalBounds());
 - 
 -         g.setFont (15.0f);
 -         g.drawFittedText (getVersionInfo(), r.removeFromBottom (50), Justification::centredBottom, 3);
 - 
 -         logo->drawWithin (g, r.withTrimmedBottom (r.getHeight() / 4).toFloat(),
 -                           RectanglePlacement (RectanglePlacement::centred), 1.0f);
 -     }
 - 
 -     static String getVersionInfo()
 -     {
 -         return SystemStats::getJUCEVersion()
 -                 + newLine
 -                 + ProjucerApplication::getApp().getVersionDescription();
 -     }
 - 
 -     ScopedPointer<Drawable> logo;
 - };
 - 
 - //==============================================================================
 - ProjectContentComponent::ProjectContentComponent()
 -     : project (nullptr),
 -       currentDocument (nullptr),
 -       treeViewTabs (TabbedButtonBar::TabsAtTop)
 - {
 -     setOpaque (true);
 -     setWantsKeyboardFocus (true);
 - 
 -     addAndMakeVisible (logo = new LogoComponent());
 - 
 -     treeSizeConstrainer.setMinimumWidth (200);
 -     treeSizeConstrainer.setMaximumWidth (500);
 - 
 -     treeViewTabs.setOutline (0);
 -     treeViewTabs.getTabbedButtonBar().setMinimumTabScaleFactor (0.3);
 - 
 -     ProjucerApplication::getApp().openDocumentManager.addListener (this);
 - 
 -     Desktop::getInstance().addFocusChangeListener (this);
 -     startTimer (1600);
 - }
 - 
 - ProjectContentComponent::~ProjectContentComponent()
 - {
 -     Desktop::getInstance().removeFocusChangeListener (this);
 -     killChildProcess();
 - 
 -     ProjucerApplication::getApp().openDocumentManager.removeListener (this);
 - 
 -     logo = nullptr;
 -     setProject (nullptr);
 -     contentView = nullptr;
 -     removeChildComponent (&bubbleMessage);
 -     jassert (getNumChildComponents() <= 1);
 - }
 - 
 - void ProjectContentComponent::paint (Graphics& g)
 - {
 -     ProjucerLookAndFeel::fillWithBackgroundTexture (*this, g);
 - }
 - 
 - void ProjectContentComponent::paintOverChildren (Graphics& g)
 - {
 -     if (resizerBar != nullptr)
 -     {
 -         const int shadowSize = 15;
 -         const int x = resizerBar->getX();
 - 
 -         ColourGradient cg (Colours::black.withAlpha (0.25f), (float) x, 0,
 -                            Colours::transparentBlack,        (float) (x - shadowSize), 0, false);
 -         cg.addColour (0.4, Colours::black.withAlpha (0.07f));
 -         cg.addColour (0.6, Colours::black.withAlpha (0.02f));
 - 
 -         g.setGradientFill (cg);
 -         g.fillRect (x - shadowSize, 0, shadowSize, getHeight());
 -     }
 - }
 - 
 - void ProjectContentComponent::resized()
 - {
 -     Rectangle<int> r (getLocalBounds());
 - 
 -     if (treeViewTabs.isVisible())
 -         treeViewTabs.setBounds (r.removeFromLeft (treeViewTabs.getWidth()));
 - 
 -     if (resizerBar != nullptr)
 -         resizerBar->setBounds (r.withWidth (4));
 - 
 -     if (contentView != nullptr)
 -         contentView->setBounds (r);
 - 
 -     if (logo != nullptr)
 -         logo->setBounds (r.reduced (r.getWidth() / 4, r.getHeight() / 4));
 - }
 - 
 - void ProjectContentComponent::lookAndFeelChanged()
 - {
 -     repaint();
 - }
 - 
 - void ProjectContentComponent::childBoundsChanged (Component* child)
 - {
 -     if (child == &treeViewTabs)
 -         resized();
 - }
 - 
 - void ProjectContentComponent::setProject (Project* newProject)
 - {
 -     if (project != newProject)
 -     {
 -         lastCrashMessage = String();
 -         killChildProcess();
 - 
 -         if (project != nullptr)
 -             project->removeChangeListener (this);
 - 
 -         contentView = nullptr;
 -         resizerBar = nullptr;
 - 
 -         deleteProjectTabs();
 -         project = newProject;
 -         rebuildProjectTabs();
 -     }
 - }
 - 
 - void ProjectContentComponent::rebuildProjectTabs()
 - {
 -     deleteProjectTabs();
 - 
 -     if (project != nullptr)
 -     {
 -         addAndMakeVisible (treeViewTabs);
 - 
 -         createProjectTabs();
 - 
 -         PropertiesFile& settings = project->getStoredProperties();
 - 
 -         const String lastTabName (settings.getValue ("lastTab"));
 -         int lastTabIndex = treeViewTabs.getTabNames().indexOf (lastTabName);
 - 
 -         if (lastTabIndex < 0 || lastTabIndex > treeViewTabs.getNumTabs())
 -             lastTabIndex = 1;
 - 
 -         treeViewTabs.setCurrentTabIndex (lastTabIndex);
 - 
 -         int lastTreeWidth = settings.getValue ("projectPanelWidth").getIntValue();
 -         if (lastTreeWidth < 150)
 -             lastTreeWidth = 240;
 - 
 -         treeViewTabs.setBounds (0, 0, lastTreeWidth, getHeight());
 - 
 -         addAndMakeVisible (resizerBar = new ResizableEdgeComponent (&treeViewTabs, &treeSizeConstrainer,
 -                                                                     ResizableEdgeComponent::rightEdge));
 -         resizerBar->setAlwaysOnTop (true);
 - 
 -         project->addChangeListener (this);
 - 
 -         updateMissingFileStatuses();
 -     }
 -     else
 -     {
 -         treeViewTabs.setVisible (false);
 -     }
 - 
 -     resized();
 - }
 - 
 - //==============================================================================
 - struct BuildTabComponent  : public ConcertinaPanel
 - {
 -     BuildTabComponent (CompileEngineChildProcess* child, ProjucerAppClasses::ErrorListComp* errorList)
 -         : errorListComp (errorList)
 -     {
 -         CurrentActivitiesComp* activities = new CurrentActivitiesComp (child->activityList);
 -         ComponentListComp* comps = new ComponentListComp (*child);
 - 
 -         addPanel (-1, errorList, true);
 -         addPanel (-1, comps, true);
 -         addPanel (-1, activities, true);
 - 
 -         setMaximumPanelSize (activities, CurrentActivitiesComp::getMaxPanelHeight());
 -         setPanelSize (errorList, 200, false);
 -         setPanelSize (comps, 300, false);
 -     }
 - 
 -     Component::SafePointer<ProjucerAppClasses::ErrorListComp> errorListComp;
 - };
 - 
 - struct ProjucerDisabledComp   : public Component,
 -                                 private Button::Listener
 - {
 -     ProjucerDisabledComp (String message, bool canLogin, bool requirePurchase = false,
 -                           const String& loginName = String())
 -               : isPurchaseButton (requirePurchase)
 -     {
 -         infoLabel.setColour (Label::textColourId, findColour (mainBackgroundColourId).contrasting (0.7f));
 -         infoLabel.setJustificationType (Justification::centred);
 -         infoLabel.setText (message, dontSendNotification);
 -         addAndMakeVisible (infoLabel);
 - 
 -         if (canLogin)
 -         {
 -             addAndMakeVisible (loginButton);
 -             loginButton.addListener (this);
 - 
 -             if (isPurchaseButton)
 -             {
 -                 loginButton.setButtonText ("Purchase JUCE Pro...");
 -                 signOutButton = new TextButton (String ("Sign Out ") + loginName);
 -                 addAndMakeVisible (*signOutButton);
 -                 signOutButton->addListener (this);
 -             }
 -         }
 -     }
 - 
 -     void resized() override
 -     {
 -         infoLabel.centreWithSize (proportionOfWidth (0.9f), 200);
 -         loginButton.setSize (jmin (getWidth() - 10, 150), 22);
 -         loginButton.setCentrePosition (infoLabel.getBounds().getCentreX(),
 -                                        infoLabel.getBottom() + loginButton.getHeight() * 2);
 - 
 -         if (signOutButton != nullptr)
 -         {
 -             signOutButton->setSize (jmin (getWidth() - 10, 150), 22);
 -             signOutButton->setCentrePosition (infoLabel.getBounds().getCentreX(),
 -                                               loginButton.getBottom() + 20);
 -         }
 -     }
 - 
 -     void buttonClicked (Button* btn) override
 -     {
 -         if (btn == &loginButton)
 -         {
 -             if (isPurchaseButton)
 -                 URL ("http://www.juce.com").launchInDefaultBrowser();
 -             else
 -                 ProjucerApplication::getApp().showLoginForm();
 -         }
 -         else if (btn == signOutButton.get())
 -         {
 -             ProjucerLicences::getInstance()->logout();
 -             ProjucerApplication::getApp().updateAllBuildTabs();
 -         }
 -     }
 - 
 -     Label infoLabel { "info", String() };
 -     TextButton loginButton { "Log-in..." };
 -     ScopedPointer<TextButton> signOutButton;
 -     bool isPurchaseButton;
 - };
 - 
 - struct EnableBuildComp   : public Component
 - {
 -     EnableBuildComp()
 -     {
 -         addAndMakeVisible (&enableButton);
 -         enableButton.setCommandToTrigger (&ProjucerApplication::getCommandManager(), CommandIDs::enableBuild, true);
 -     }
 - 
 -     void resized() override
 -     {
 -         enableButton.centreWithSize (jmin (getWidth() - 10, 150), 22);
 -     }
 - 
 -     void paint (Graphics& g) override
 -     {
 -         if (ProjectContentComponent* ppc = findParentComponentOfClass<ProjectContentComponent>())
 -         {
 -             g.setColour (findColour (mainBackgroundColourId).contrasting (0.7f));
 -             g.setFont (13.0f);
 -             g.drawFittedText (ppc->lastCrashMessage,
 -                               getLocalBounds().reduced (8).withBottom (enableButton.getY() - 20),
 -                               Justification::centredBottom, 10);
 -         }
 -     }
 - 
 -     TextButton enableButton { "Restart Compiler" };
 - };
 - 
 - //==============================================================================
 - Component* ProjectContentComponent::createBuildTab (CompileEngineChildProcess* child)
 - {
 -    #if JUCE_WINDOWS
 -     ignoreUnused (child);
 -     return new ProjucerDisabledComp ("Windows support is still under development - "
 -                                      "please check for updates at www.juce.com!", false);
 -    #elif JUCE_LINUX
 -     ignoreUnused (child);
 -     return new ProjucerDisabledComp ("Linux support is still under development - "
 -                                      "please check for updates at www.juce.com!", false);
 -    #else
 -     if (child != nullptr)
 -     {
 -         child->crashHandler = [this] (const String& m) { this->handleCrash (m); };
 - 
 -         return new BuildTabComponent (child, new ProjucerAppClasses::ErrorListComp (child->errorList));
 -     }
 - 
 -     auto& unlockStatus = *ProjucerLicences::getInstance();
 - 
 -     if (unlockStatus.hasLiveCodingLicence()
 -         && project != nullptr
 -         && LiveBuildProjectSettings::isBuildDisabled (*project))
 -          return new EnableBuildComp();
 - 
 -     if (unlockStatus.isLoggedIn())
 -         return new ProjucerDisabledComp (String ("The Projucer's live-build features are currently disabled!") + newLine
 -                                           + newLine
 -                                           + "Your account " + unlockStatus.getLoginName().quoted()
 -                                           + " does not have an asscociated JUCE Pro license:",
 -                                          true, true, unlockStatus.getLoginName());
 - 
 -     if (! unlockStatus.isDLLPresent())
 -         return new ProjucerDisabledComp (String ("The live-building DLL is missing!") + newLine
 -                                           + newLine
 -                                           + "To enable the compiler, you'll need to install the missing DLL "
 -                                           + CompileEngineDLL::getDLLName().quoted() + newLine
 -                                           + newLine
 -                                           + "Visit the JUCE website/forum for more help on getting and installing the DLL!", false);
 - 
 -     return new ProjucerDisabledComp ("The Projucer's live-build features are currently disabled!\n\n"
 -                                      "To enable them, you'll need to log-in with your JUCE account details:", true, false);
 -    #endif
 - }
 - 
 - BuildTabComponent* findBuildTab (const TabbedComponent& tabs)
 - {
 -     return dynamic_cast<BuildTabComponent*> (tabs.getTabContentComponent (2));
 - }
 - 
 - bool ProjectContentComponent::isBuildTabShowing() const
 - {
 -     return findBuildTab (treeViewTabs) != nullptr;
 - }
 - 
 - bool ProjectContentComponent::isLoggedInTabShowing() const
 - {
 -     return isBuildTabShowing() || dynamic_cast<EnableBuildComp*> (treeViewTabs.getTabContentComponent (2)) != nullptr;
 - }
 - 
 - void ProjectContentComponent::createProjectTabs()
 - {
 -     jassert (project != nullptr);
 -     const Colour tabColour (Colours::transparentBlack);
 - 
 -     treeViewTabs.addTab ("Files",  tabColour, new FileTreePanel (*project), true);
 -     treeViewTabs.addTab ("Config", tabColour, new ConfigTreePanel (*project), true);
 - 
 -     const CompileEngineChildProcess::Ptr childProc (getChildProcess());
 - 
 -     treeViewTabs.addTab ("Build", Colours::transparentBlack, createBuildTab (childProc), true);
 - 
 -     if (childProc != nullptr)
 -         treeViewTabs.getTabbedButtonBar().getTabButton (2)
 -             ->setExtraComponent (new BuildStatusTabComp (childProc->errorList,
 -                                                          childProc->activityList),
 -                                  TabBarButton::afterText);
 - }
 - 
 - void ProjectContentComponent::deleteProjectTabs()
 - {
 -     if (project != nullptr && treeViewTabs.isShowing())
 -     {
 -         PropertiesFile& settings = project->getStoredProperties();
 - 
 -         if (treeViewTabs.getWidth() > 0)
 -             settings.setValue ("projectPanelWidth", treeViewTabs.getWidth());
 - 
 -         if (treeViewTabs.getNumTabs() > 0)
 -             settings.setValue ("lastTab", treeViewTabs.getCurrentTabName());
 -     }
 - 
 -     treeViewTabs.clearTabs();
 - }
 - 
 - void ProjectContentComponent::saveTreeViewState()
 - {
 -     for (int i = treeViewTabs.getNumTabs(); --i >= 0;)
 -         if (TreePanelBase* t = dynamic_cast<TreePanelBase*> (treeViewTabs.getTabContentComponent (i)))
 -             t->saveOpenness();
 - }
 - 
 - void ProjectContentComponent::saveOpenDocumentList()
 - {
 -     if (project != nullptr)
 -     {
 -         ScopedPointer<XmlElement> xml (recentDocumentList.createXML());
 - 
 -         if (xml != nullptr)
 -             project->getStoredProperties().setValue ("lastDocs", xml);
 -     }
 - }
 - 
 - void ProjectContentComponent::reloadLastOpenDocuments()
 - {
 -     if (project != nullptr)
 -     {
 -         ScopedPointer<XmlElement> xml (project->getStoredProperties().getXmlValue ("lastDocs"));
 - 
 -         if (xml != nullptr)
 -         {
 -             recentDocumentList.restoreFromXML (*project, *xml);
 -             showDocument (recentDocumentList.getCurrentDocument(), true);
 -         }
 -     }
 - }
 - 
 - bool ProjectContentComponent::documentAboutToClose (OpenDocumentManager::Document* document)
 - {
 -     hideDocument (document);
 -     return true;
 - }
 - 
 - void ProjectContentComponent::changeListenerCallback (ChangeBroadcaster*)
 - {
 -     updateMissingFileStatuses();
 - }
 - 
 - void ProjectContentComponent::updateMissingFileStatuses()
 - {
 -     if (FileTreePanel* tree = dynamic_cast<FileTreePanel*> (treeViewTabs.getTabContentComponent (0)))
 -         tree->updateMissingFileStatuses();
 - }
 - 
 - bool ProjectContentComponent::showEditorForFile (const File& f, bool grabFocus)
 - {
 -     return getCurrentFile() == f
 -             || showDocument (ProjucerApplication::getApp().openDocumentManager.openFile (project, f), grabFocus);
 - }
 - 
 - bool ProjectContentComponent::hasFileInRecentList (const File& f) const
 - {
 -     return recentDocumentList.contains (f);
 - }
 - 
 - File ProjectContentComponent::getCurrentFile() const
 - {
 -     return currentDocument != nullptr ? currentDocument->getFile()
 -                                       : File::nonexistent;
 - }
 - 
 - bool ProjectContentComponent::showDocument (OpenDocumentManager::Document* doc, bool grabFocus)
 - {
 -     if (doc == nullptr)
 -         return false;
 - 
 -     if (doc->hasFileBeenModifiedExternally())
 -         doc->reloadFromFile();
 - 
 -     if (doc == getCurrentDocument() && contentView != nullptr)
 -     {
 -         if (grabFocus)
 -             contentView->grabKeyboardFocus();
 - 
 -         return true;
 -     }
 - 
 -     recentDocumentList.newDocumentOpened (doc);
 - 
 -     bool opened = setEditorComponent (doc->createEditor(), doc);
 - 
 -     if (opened && grabFocus)
 -         contentView->grabKeyboardFocus();
 - 
 -     return opened;
 - }
 - 
 - void ProjectContentComponent::hideEditor()
 - {
 -     currentDocument = nullptr;
 -     contentView = nullptr;
 -     updateMainWindowTitle();
 -     ProjucerApplication::getCommandManager().commandStatusChanged();
 -     resized();
 - }
 - 
 - void ProjectContentComponent::hideDocument (OpenDocumentManager::Document* doc)
 - {
 -     if (doc == currentDocument)
 -     {
 -         if (OpenDocumentManager::Document* replacement = recentDocumentList.getClosestPreviousDocOtherThan (doc))
 -             showDocument (replacement, true);
 -         else
 -             hideEditor();
 -     }
 - }
 - 
 - bool ProjectContentComponent::setEditorComponent (Component* editor,
 -                                                   OpenDocumentManager::Document* doc)
 - {
 -     if (editor != nullptr)
 -     {
 -         contentView = nullptr;
 -         contentView = editor;
 -         currentDocument = doc;
 -         addAndMakeVisible (editor);
 -         resized();
 - 
 -         updateMainWindowTitle();
 -         ProjucerApplication::getCommandManager().commandStatusChanged();
 -         return true;
 -     }
 - 
 -     updateMainWindowTitle();
 -     return false;
 - }
 - 
 - void ProjectContentComponent::closeDocument()
 - {
 -     if (currentDocument != nullptr)
 -         ProjucerApplication::getApp().openDocumentManager.closeDocument (currentDocument, true);
 -     else if (contentView != nullptr)
 -         if (! goToPreviousFile())
 -             hideEditor();
 - }
 - 
 - static void showSaveWarning (OpenDocumentManager::Document* currentDocument)
 - {
 -     AlertWindow::showMessageBox (AlertWindow::WarningIcon,
 -                                  TRANS("Save failed!"),
 -                                  TRANS("Couldn't save the file:")
 -                                    + "\n" + currentDocument->getFile().getFullPathName());
 - }
 - 
 - void ProjectContentComponent::saveDocument()
 - {
 -     if (currentDocument != nullptr)
 -     {
 -         if (! currentDocument->save())
 -             showSaveWarning (currentDocument);
 -     }
 -     else
 -         saveProject();
 - 
 -     updateMainWindowTitle();
 - }
 - 
 - void ProjectContentComponent::saveAs()
 - {
 -     if (currentDocument != nullptr && ! currentDocument->saveAs())
 -         showSaveWarning (currentDocument);
 - }
 - 
 - bool ProjectContentComponent::goToPreviousFile()
 - {
 -     OpenDocumentManager::Document* doc = recentDocumentList.getCurrentDocument();
 - 
 -     if (doc == nullptr || doc == getCurrentDocument())
 -         doc = recentDocumentList.getPrevious();
 - 
 -     return showDocument (doc, true);
 - }
 - 
 - bool ProjectContentComponent::goToNextFile()
 - {
 -     return showDocument (recentDocumentList.getNext(), true);
 - }
 - 
 - bool ProjectContentComponent::canGoToCounterpart() const
 - {
 -     return currentDocument != nullptr
 -             && currentDocument->getCounterpartFile().exists();
 - }
 - 
 - bool ProjectContentComponent::goToCounterpart()
 - {
 -     if (currentDocument != nullptr)
 -     {
 -         const File file (currentDocument->getCounterpartFile());
 - 
 -         if (file.exists())
 -             return showEditorForFile (file, true);
 -     }
 - 
 -     return false;
 - }
 - 
 - bool ProjectContentComponent::saveProject()
 - {
 -     return project != nullptr
 -             && project->save (true, true) == FileBasedDocument::savedOk;
 - }
 - 
 - void ProjectContentComponent::closeProject()
 - {
 -     if (MainWindow* const mw = findParentComponentOfClass<MainWindow>())
 -         mw->closeCurrentProject();
 - }
 - 
 - void ProjectContentComponent::showFilesTab()
 - {
 -     treeViewTabs.setCurrentTabIndex (0);
 - }
 - 
 - void ProjectContentComponent::showConfigTab()
 - {
 -     treeViewTabs.setCurrentTabIndex (1);
 - }
 - 
 - void ProjectContentComponent::showProjectSettings()
 - {
 -     showConfigTab();
 - 
 -     if (ConfigTreePanel* const tree = dynamic_cast<ConfigTreePanel*> (treeViewTabs.getCurrentContentComponent()))
 -         tree->showProjectSettings();
 - }
 - 
 - void ProjectContentComponent::showModules()
 - {
 -     showConfigTab();
 - 
 -     if (ConfigTreePanel* const tree = dynamic_cast<ConfigTreePanel*> (treeViewTabs.getCurrentContentComponent()))
 -         tree->showModules();
 - }
 - 
 - void ProjectContentComponent::showModule (const String& moduleID)
 - {
 -     showConfigTab();
 - 
 -     if (ConfigTreePanel* const tree = dynamic_cast<ConfigTreePanel*> (treeViewTabs.getCurrentContentComponent()))
 -         tree->showModule (moduleID);
 - }
 - 
 - StringArray ProjectContentComponent::getExportersWhichCanLaunch() const
 - {
 -     StringArray s;
 - 
 -     if (project != nullptr)
 -         for (Project::ExporterIterator exporter (*project); exporter.next();)
 -             if (exporter->canLaunchProject())
 -                 s.add (exporter->getName());
 - 
 -     return s;
 - }
 - 
 - void ProjectContentComponent::openInIDE (int exporterIndex, bool saveFirst)
 - {
 -     if (saveFirst)
 -         saveProject();
 - 
 -     int i = 0;
 - 
 -     if (project != nullptr)
 -         for (Project::ExporterIterator exporter (*project); exporter.next();)
 -             if (exporter->canLaunchProject())
 -                 if (i++ == exporterIndex && exporter->launchProject())
 -                     break;
 - }
 - 
 - static void openIDEMenuCallback (int result, ProjectContentComponent* comp, bool saveFirst)
 - {
 -     if (comp != nullptr && result > 0)
 -         comp->openInIDE (result - 1, saveFirst);
 - }
 - 
 - void ProjectContentComponent::openInIDE (bool saveFirst)
 - {
 -     if (project != nullptr)
 -     {
 -         StringArray possibleExporters = getExportersWhichCanLaunch();
 - 
 -         if (possibleExporters.size() > 1)
 -         {
 -             PopupMenu menu;
 - 
 -             for (int i = 0; i < possibleExporters.size(); ++i)
 -                 menu.addItem (i + 1, possibleExporters[i]);
 - 
 -             menu.showMenuAsync (PopupMenu::Options(),
 -                                 ModalCallbackFunction::forComponent (openIDEMenuCallback, this, saveFirst));
 -         }
 -         else
 -         {
 -             openInIDE (0, saveFirst);
 -         }
 -     }
 - }
 - 
 - static void newExporterMenuCallback (int result, ProjectContentComponent* comp)
 - {
 -     if (comp != nullptr && result > 0)
 -     {
 -         if (Project* p = comp->getProject())
 -         {
 -             String exporterName (ProjectExporter::getExporterNames() [result - 1]);
 - 
 -             if (exporterName.isNotEmpty())
 -                 p->addNewExporter (exporterName);
 -         }
 -     }
 - }
 - 
 - void ProjectContentComponent::showNewExporterMenu()
 - {
 -     if (project != nullptr)
 -     {
 -         PopupMenu menu;
 - 
 -         menu.addSectionHeader ("Create a new export target:");
 - 
 -         Array<ProjectExporter::ExporterTypeInfo> exporters (ProjectExporter::getExporterTypes());
 - 
 -         for (int i = 0; i < exporters.size(); ++i)
 -         {
 -             const ProjectExporter::ExporterTypeInfo& type = exporters.getReference(i);
 - 
 -             menu.addItem (i + 1, type.name, true, false, type.getIcon());
 -         }
 - 
 -         menu.showMenuAsync (PopupMenu::Options(),
 -                             ModalCallbackFunction::forComponent (newExporterMenuCallback, this));
 -     }
 - }
 - 
 - void ProjectContentComponent::deleteSelectedTreeItems()
 - {
 -     if (TreePanelBase* const tree = dynamic_cast<TreePanelBase*> (treeViewTabs.getCurrentContentComponent()))
 -         tree->deleteSelectedItems();
 - }
 - 
 - void ProjectContentComponent::updateMainWindowTitle()
 - {
 -     if (MainWindow* mw = findParentComponentOfClass<MainWindow>())
 -     {
 -         String title;
 -         File file;
 -         bool edited = false;
 - 
 -         if (currentDocument != nullptr)
 -         {
 -             title = currentDocument->getName();
 -             edited = currentDocument->needsSaving();
 -             file = currentDocument->getFile();
 -         }
 - 
 -         if (ComponentPeer* peer = mw->getPeer())
 -         {
 -             if (! peer->setDocumentEditedStatus (edited))
 -                 if (edited)
 -                     title << "*";
 - 
 -             peer->setRepresentedFile (file);
 -         }
 - 
 -         mw->updateTitle (title);
 -     }
 - }
 - 
 - void ProjectContentComponent::showBubbleMessage (Rectangle<int> pos, const String& text)
 - {
 -     addChildComponent (bubbleMessage);
 -     bubbleMessage.setColour (BubbleComponent::backgroundColourId, Colours::white.withAlpha (0.7f));
 -     bubbleMessage.setColour (BubbleComponent::outlineColourId, Colours::black.withAlpha (0.8f));
 -     bubbleMessage.setAlwaysOnTop (true);
 - 
 -     bubbleMessage.showAt (pos, AttributedString (text), 3000, true, false);
 - }
 - 
 - //==============================================================================
 - void ProjectContentComponent::showTranslationTool()
 - {
 -     if (translationTool != nullptr)
 -     {
 -         translationTool->toFront (true);
 -     }
 -     else if (project != nullptr)
 -     {
 -         new FloatingToolWindow ("Translation File Builder",
 -                                 "transToolWindowPos",
 -                                 new TranslationToolComponent(),
 -                                 translationTool,
 -                                 600, 700,
 -                                 600, 400, 10000, 10000);
 -     }
 - }
 - 
 - //==============================================================================
 - struct AsyncCommandRetrier  : public Timer
 - {
 -     AsyncCommandRetrier (const ApplicationCommandTarget::InvocationInfo& i)  : info (i)
 -     {
 -         info.originatingComponent = nullptr;
 -         startTimer (500);
 -     }
 - 
 -     void timerCallback() override
 -     {
 -         stopTimer();
 -         ProjucerApplication::getCommandManager().invoke (info, true);
 -         delete this;
 -     }
 - 
 -     ApplicationCommandTarget::InvocationInfo info;
 - 
 -     JUCE_DECLARE_NON_COPYABLE (AsyncCommandRetrier)
 - };
 - 
 - bool reinvokeCommandAfterCancellingModalComps (const ApplicationCommandTarget::InvocationInfo& info)
 - {
 -     if (ModalComponentManager::getInstance()->cancelAllModalComponents())
 -     {
 -         new AsyncCommandRetrier (info);
 -         return true;
 -     }
 - 
 -     return false;
 - }
 - 
 - //==============================================================================
 - ApplicationCommandTarget* ProjectContentComponent::getNextCommandTarget()
 - {
 -     return findFirstTargetParentComponent();
 - }
 - 
 - void ProjectContentComponent::getAllCommands (Array <CommandID>& commands)
 - {
 -     const CommandID ids[] = { CommandIDs::saveDocument,
 -                               CommandIDs::saveDocumentAs,
 -                               CommandIDs::closeDocument,
 -                               CommandIDs::saveProject,
 -                               CommandIDs::closeProject,
 -                               CommandIDs::openInIDE,
 -                               CommandIDs::saveAndOpenInIDE,
 -                               CommandIDs::createNewExporter,
 -                               CommandIDs::showFilePanel,
 -                               CommandIDs::showConfigPanel,
 -                               CommandIDs::showProjectSettings,
 -                               CommandIDs::showProjectModules,
 -                               CommandIDs::goToPreviousDoc,
 -                               CommandIDs::goToNextDoc,
 -                               CommandIDs::goToCounterpart,
 -                               CommandIDs::deleteSelectedItem,
 -                               CommandIDs::showTranslationTool,
 -                               CommandIDs::showBuildTab,
 -                               CommandIDs::cleanAll,
 -                               CommandIDs::enableBuild,
 -                               CommandIDs::buildNow,
 -                               CommandIDs::toggleContinuousBuild,
 -                               CommandIDs::showWarnings,
 -                               CommandIDs::reinstantiateComp,
 -                               CommandIDs::launchApp,
 -                               CommandIDs::killApp,
 -                               CommandIDs::nextError,
 -                               CommandIDs::prevError };
 - 
 -     commands.addArray (ids, numElementsInArray (ids));
 - }
 - 
 - void ProjectContentComponent::getCommandInfo (const CommandID commandID, ApplicationCommandInfo& result)
 - {
 -     String documentName;
 -     if (currentDocument != nullptr)
 -         documentName = " '" + currentDocument->getName().substring (0, 32) + "'";
 - 
 -    #if JUCE_MAC
 -     const ModifierKeys cmdCtrl (ModifierKeys::ctrlModifier | ModifierKeys::commandModifier);
 -    #else
 -     const ModifierKeys cmdCtrl (ModifierKeys::ctrlModifier | ModifierKeys::altModifier);
 -    #endif
 - 
 -     switch (commandID)
 -     {
 -     case CommandIDs::saveProject:
 -         result.setInfo ("Save Project",
 -                         "Saves the current project",
 -                         CommandCategories::general, 0);
 -         result.setActive (project != nullptr);
 -         break;
 - 
 -     case CommandIDs::closeProject:
 -         result.setInfo ("Close Project",
 -                         "Closes the current project",
 -                         CommandCategories::general, 0);
 -         result.setActive (project != nullptr);
 -         break;
 - 
 -     case CommandIDs::saveDocument:
 -         result.setInfo ("Save" + documentName,
 -                         "Saves the current document",
 -                         CommandCategories::general, 0);
 -         result.setActive (currentDocument != nullptr || project != nullptr);
 -         result.defaultKeypresses.add (KeyPress ('s', ModifierKeys::commandModifier, 0));
 -         break;
 - 
 -     case CommandIDs::saveDocumentAs:
 -         result.setInfo ("Save As...",
 -                         "Saves the current document to a new location",
 -                         CommandCategories::general, 0);
 -         result.setActive (currentDocument != nullptr);
 -         result.defaultKeypresses.add (KeyPress ('s', ModifierKeys::commandModifier | ModifierKeys::shiftModifier, 0));
 -         break;
 - 
 -     case CommandIDs::closeDocument:
 -         result.setInfo ("Close" + documentName,
 -                         "Closes the current document",
 -                         CommandCategories::general, 0);
 -         result.setActive (contentView != nullptr);
 -         result.defaultKeypresses.add (KeyPress ('w', cmdCtrl, 0));
 -         break;
 - 
 -     case CommandIDs::goToPreviousDoc:
 -         result.setInfo ("Previous Document", "Go to previous document", CommandCategories::general, 0);
 -         result.setActive (recentDocumentList.canGoToPrevious());
 -         result.defaultKeypresses.add (KeyPress (KeyPress::leftKey, cmdCtrl, 0));
 -         break;
 - 
 -     case CommandIDs::goToNextDoc:
 -         result.setInfo ("Next Document", "Go to next document", CommandCategories::general, 0);
 -         result.setActive (recentDocumentList.canGoToNext());
 -         result.defaultKeypresses.add (KeyPress (KeyPress::rightKey, cmdCtrl, 0));
 -         break;
 - 
 -     case CommandIDs::goToCounterpart:
 -         result.setInfo ("Open corresponding header or cpp file", "Open counterpart file", CommandCategories::general, 0);
 -         result.setActive (canGoToCounterpart());
 -         result.defaultKeypresses.add (KeyPress (KeyPress::upKey, cmdCtrl, 0));
 -         break;
 - 
 -     case CommandIDs::openInIDE:
 -         result.setInfo ("Open in IDE...",
 - 
 -                         "Launches the project in an external IDE",
 -                         CommandCategories::general, 0);
 -         result.setActive (ProjectExporter::canProjectBeLaunched (project));
 -         break;
 - 
 -     case CommandIDs::saveAndOpenInIDE:
 -         result.setInfo ("Save Project and Open in IDE...",
 - 
 -                         "Saves the project and launches it in an external IDE",
 -                         CommandCategories::general, 0);
 -         result.setActive (ProjectExporter::canProjectBeLaunched (project));
 -         result.defaultKeypresses.add (KeyPress ('l', ModifierKeys::commandModifier | ModifierKeys::shiftModifier, 0));
 -         break;
 - 
 -     case CommandIDs::createNewExporter:
 -         result.setInfo ("Create New Exporter...",
 -                         "Creates a new exporter for a compiler type",
 -                         CommandCategories::general, 0);
 -         result.setActive (project != nullptr);
 -         break;
 - 
 -     case CommandIDs::showFilePanel:
 -         result.setInfo ("Show File Panel",
 -                         "Shows the tree of files for this project",
 -                         CommandCategories::general, 0);
 -         result.setActive (project != nullptr);
 -         result.defaultKeypresses.add (KeyPress ('p', ModifierKeys::commandModifier, 0));
 -         break;
 - 
 -     case CommandIDs::showConfigPanel:
 -         result.setInfo ("Show Config Panel",
 -                         "Shows the build options for the project",
 -                         CommandCategories::general, 0);
 -         result.setActive (project != nullptr);
 -         result.defaultKeypresses.add (KeyPress ('i', ModifierKeys::commandModifier, 0));
 -         break;
 - 
 -     case CommandIDs::showProjectSettings:
 -         result.setInfo ("Show Project Settings",
 -                         "Shows the main project options page",
 -                         CommandCategories::general, 0);
 -         result.setActive (project != nullptr);
 -         result.defaultKeypresses.add (KeyPress ('i', ModifierKeys::commandModifier | ModifierKeys::shiftModifier, 0));
 -         break;
 - 
 -     case CommandIDs::showProjectModules:
 -         result.setInfo ("Show Project Modules",
 -                         "Shows the project's list of modules",
 -                         CommandCategories::general, 0);
 -         result.setActive (project != nullptr);
 -         result.defaultKeypresses.add (KeyPress ('m', ModifierKeys::commandModifier | ModifierKeys::shiftModifier, 0));
 -         break;
 - 
 -     case CommandIDs::deleteSelectedItem:
 -         result.setInfo ("Delete Selected File", String::empty, CommandCategories::general, 0);
 -         result.defaultKeypresses.add (KeyPress (KeyPress::deleteKey, 0, 0));
 -         result.defaultKeypresses.add (KeyPress (KeyPress::backspaceKey, 0, 0));
 -         result.setActive (dynamic_cast<TreePanelBase*> (treeViewTabs.getCurrentContentComponent()) != nullptr);
 -         break;
 - 
 -     case CommandIDs::showTranslationTool:
 -         result.setInfo ("Translation File Builder", "Shows the translation file helper tool", CommandCategories::general, 0);
 -         break;
 - 
 -     case CommandIDs::showBuildTab:
 -         result.setInfo ("Show Build Panel", "Shows the build panel", CommandCategories::general, 0);
 -         //result.defaultKeypresses.add (KeyPress ('b', ModifierKeys::commandModifier, 0));
 -         break;
 - 
 -     case CommandIDs::cleanAll:
 -         result.setInfo ("Clean All", "Cleans all intermediate files", CommandCategories::general, 0);
 -         result.defaultKeypresses.add (KeyPress ('k', ModifierKeys::commandModifier | ModifierKeys::shiftModifier, 0));
 -         result.setActive (project != nullptr);
 -         break;
 - 
 -     case CommandIDs::enableBuild:
 -         result.setInfo ("Enable Compilation", "Enables/disables the compiler", CommandCategories::general, 0);
 -         result.defaultKeypresses.add (KeyPress ('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 (KeyPress ('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::showWarnings:
 -         result.setInfo ("Show Warnings", "Shows or hides compilation warnings", CommandCategories::general, 0);
 -         result.setActive (project != nullptr);
 -         result.setTicked (areWarningsEnabled());
 -         break;
 - 
 -     case CommandIDs::launchApp:
 -         result.setInfo ("Launch Application", "Invokes the app's main() function", CommandCategories::general, 0);
 -         result.defaultKeypresses.add (KeyPress ('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 (KeyPress ('.', 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 (KeyPress ('r', ModifierKeys::commandModifier | ModifierKeys::shiftModifier, 0));
 -         result.setActive (childProcess != nullptr);
 -         break;
 - 
 -     case CommandIDs::nextError:
 -         result.setInfo ("Highlight next error", "Jumps to the next error or warning", CommandCategories::general, 0);
 -         result.defaultKeypresses.add (KeyPress ('e', 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 (KeyPress ('e', ModifierKeys::commandModifier | ModifierKeys::shiftModifier, 0));
 -         result.setActive (childProcess != nullptr && ! childProcess->errorList.isEmpty());
 -         break;
 - 
 -     default:
 -         break;
 -     }
 - }
 - 
 - bool ProjectContentComponent::perform (const InvocationInfo& info)
 - {
 -     switch (info.commandID)
 -     {
 -         case CommandIDs::saveProject:
 -         case CommandIDs::closeProject:
 -         case CommandIDs::saveDocument:
 -         case CommandIDs::saveDocumentAs:
 -         case CommandIDs::closeDocument:
 -         case CommandIDs::goToPreviousDoc:
 -         case CommandIDs::goToNextDoc:
 -         case CommandIDs::goToCounterpart:
 -         case CommandIDs::saveAndOpenInIDE:
 -             if (reinvokeCommandAfterCancellingModalComps (info))
 -             {
 -                 grabKeyboardFocus(); // to force any open labels to close their text editors
 -                 return true;
 -             }
 - 
 -             break;
 - 
 -         default:
 -             break;
 -     }
 - 
 -     if (isCurrentlyBlockedByAnotherModalComponent())
 -         return false;
 - 
 -     switch (info.commandID)
 -     {
 -         case CommandIDs::saveProject:               saveProject(); break;
 -         case CommandIDs::closeProject:              closeProject(); break;
 -         case CommandIDs::saveDocument:              saveDocument(); break;
 -         case CommandIDs::saveDocumentAs:            saveAs(); break;
 - 
 -         case CommandIDs::closeDocument:             closeDocument(); break;
 -         case CommandIDs::goToPreviousDoc:           goToPreviousFile(); break;
 -         case CommandIDs::goToNextDoc:               goToNextFile(); break;
 -         case CommandIDs::goToCounterpart:           goToCounterpart(); break;
 - 
 -         case CommandIDs::showFilePanel:             showFilesTab(); break;
 -         case CommandIDs::showConfigPanel:           showConfigTab(); break;
 -         case CommandIDs::showProjectSettings:       showProjectSettings(); break;
 -         case CommandIDs::showProjectModules:        showModules(); break;
 - 
 -         case CommandIDs::openInIDE:                 openInIDE (false); break;
 -         case CommandIDs::saveAndOpenInIDE:          openInIDE (true); break;
 - 
 -         case CommandIDs::createNewExporter:         showNewExporterMenu(); break;
 - 
 -         case CommandIDs::deleteSelectedItem:        deleteSelectedTreeItems(); break;
 - 
 -         case CommandIDs::showTranslationTool:       showTranslationTool(); break;
 - 
 -         case CommandIDs::showBuildTab:              showBuildTab(); break;
 -         case CommandIDs::cleanAll:                  cleanAll(); break;
 -         case CommandIDs::enableBuild:               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;
 - 
 -         default:
 -             return false;
 -     }
 - 
 -     return true;
 - }
 - 
 - void ProjectContentComponent::getSelectedProjectItemsBeingDragged (const DragAndDropTarget::SourceDetails& dragSourceDetails,
 -                                                                    OwnedArray<Project::Item>& selectedNodes)
 - {
 -     FileTreeItemTypes::ProjectTreeItemBase::getSelectedProjectItemsBeingDragged (dragSourceDetails, selectedNodes);
 - }
 - 
 - //==============================================================================
 - void ProjectContentComponent::killChildProcess()
 - {
 -     if (childProcess != nullptr)
 -     {
 -         deleteProjectTabs();
 -         childProcess = nullptr;
 -         ProjucerApplication::getApp().childProcessCache->removeOrphans();
 -     }
 - }
 - 
 - void ProjectContentComponent::setBuildEnabled (bool b)
 - {
 -     if (project != nullptr && b != isBuildEnabled())
 -     {
 -         LiveBuildProjectSettings::setBuildDisabled (*project, ! b);
 -         killChildProcess();
 -         refreshTabsIfBuildStatusChanged();
 -     }
 - }
 - 
 - void ProjectContentComponent::showBuildTab()
 - {
 -     WeakReference<Component> currentFocus (Component::getCurrentlyFocusedComponent());
 -     treeViewTabs.setCurrentTabIndex (2);
 - 
 -     if (currentFocus != nullptr)
 -         currentFocus->grabKeyboardFocus();
 - }
 - 
 - void ProjectContentComponent::cleanAll()
 - {
 -     lastCrashMessage = String();
 - 
 -     if (childProcess != nullptr)
 -         childProcess->cleanAll();
 -     else if (Project* 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);
 -         showBuildTab();
 -     }
 - }
 - 
 - bool ProjectContentComponent::isBuildEnabled() const
 - {
 -     return project != nullptr
 -             && ! LiveBuildProjectSettings::isBuildDisabled (*project)
 -             && ProjucerLicences::getInstance()->hasLiveCodingLicence()
 -             && ProjucerLicences::getInstance()->isLoggedIn();
 - }
 - 
 - void ProjectContentComponent::refreshTabsIfBuildStatusChanged()
 - {
 -     if (project != nullptr
 -          && (treeViewTabs.getNumTabs() < 3
 -               || isBuildEnabled() != isBuildTabShowing()
 -               || ProjucerLicences::getInstance()->isLoggedIn() != isLoggedInTabShowing()))
 -         rebuildProjectTabs();
 - }
 - 
 - bool ProjectContentComponent::areWarningsEnabled() const
 - {
 -     return project != nullptr && ! LiveBuildProjectSettings::areWarningsDisabled (*project);
 - }
 - 
 - void ProjectContentComponent::updateWarningState()
 - {
 -     if (childProcess != nullptr)
 -         childProcess->errorList.setWarningsEnabled (areWarningsEnabled());
 - }
 - 
 - void ProjectContentComponent::toggleWarnings()
 - {
 -     if (project != nullptr)
 -     {
 -         LiveBuildProjectSettings::setWarningsDisabled (*project, areWarningsEnabled());
 -         updateWarningState();
 -     }
 - }
 - 
 - static ProjucerAppClasses::ErrorListComp* findErrorListComp (const TabbedComponent& tabs)
 - {
 -     if (BuildTabComponent* bt = findBuildTab (tabs))
 -         return bt->errorListComp;
 - 
 -     return nullptr;
 - }
 - 
 - void ProjectContentComponent::showNextError()
 - {
 -     if (ProjucerAppClasses::ErrorListComp* el = findErrorListComp (treeViewTabs))
 -     {
 -         showBuildTab();
 -         el->showNext();
 -     }
 - }
 - 
 - void ProjectContentComponent::showPreviousError()
 - {
 -     if (ProjucerAppClasses::ErrorListComp* el = findErrorListComp (treeViewTabs))
 -     {
 -         showBuildTab();
 -         el->showPrevious();
 -     }
 - }
 - 
 - void ProjectContentComponent::reinstantiateLivePreviewWindows()
 - {
 -     if (childProcess != nullptr)
 -         childProcess->reinstantiatePreviews();
 - }
 - 
 - 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)
 - {
 -     const bool 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();
 - }
 - 
 - ReferenceCountedObjectPtr<CompileEngineChildProcess> ProjectContentComponent::getChildProcess()
 - {
 -    #if JUCE_MAC
 -     if (childProcess == nullptr && isBuildEnabled())
 -     {
 -         childProcess = ProjucerApplication::getApp().childProcessCache->getOrCreate (*project);
 - 
 -         if (childProcess != nullptr)
 -             childProcess->setContinuousRebuild (isContinuousRebuildEnabled());
 -     }
 -    #endif
 - 
 -     return childProcess;
 - }
 - 
 - void ProjectContentComponent::handleMissingSystemHeaders()
 - {
 -    #if JUCE_MAC
 -     const String tabMessage = "Compiler not available due to missing system headers\nPlease install a recent version of Xcode";
 -     const String alertWindowMessage = "Missing system headers\nPlease install a recent version of Xcode";
 -    #elif JUCE_WINDOWS
 -     const String tabMessage = "Compiler not available due to missing system headers\nPlease install a recent version of Visual Studio and the Windows Desktop SDK";
 -     const String alertWindowMessage = "Missing system headers\nPlease install a recent version of Visual Studio and the Windows Desktop SDK";
 -    #elif JUCE_LINUX
 -     const String tabMessage = "Compiler not available due to missing system headers\nPlease do a sudo apt-get install ...";
 -     const String alertWindowMessage = "Missing system headers\nPlease do sudo apt-get install ...";
 -    #endif
 - 
 -     setBuildEnabled (false);
 - 
 -     deleteProjectTabs();
 -     createProjectTabs();
 - 
 -     ProjucerDisabledComp* buildTab = new ProjucerDisabledComp (tabMessage, false);
 - 
 -     treeViewTabs.addTab ("Build", Colours::transparentBlack, buildTab, true);
 -     showBuildTab();
 - 
 -     AlertWindow::showMessageBox (AlertWindow::AlertIconType::WarningIcon,
 -                                  "Missing system headers", alertWindowMessage);
 - }
 
 
  |