The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

804 lines
28KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. void createGUIEditorMenu (PopupMenu&);
  20. void handleGUIEditorMenuCommand (int);
  21. void registerGUIEditorCommands();
  22. //==============================================================================
  23. struct ProjucerApplication::MainMenuModel : public MenuBarModel
  24. {
  25. MainMenuModel()
  26. {
  27. setApplicationCommandManagerToWatch (&getCommandManager());
  28. }
  29. StringArray getMenuBarNames() override
  30. {
  31. return getApp().getMenuNames();
  32. }
  33. PopupMenu getMenuForIndex (int /*topLevelMenuIndex*/, const String& menuName) override
  34. {
  35. PopupMenu menu;
  36. getApp().createMenu (menu, menuName);
  37. return menu;
  38. }
  39. void menuItemSelected (int menuItemID, int /*topLevelMenuIndex*/) override
  40. {
  41. getApp().handleMainMenuCommand (menuItemID);
  42. }
  43. };
  44. //==============================================================================
  45. ProjucerApplication::ProjucerApplication() : isRunningCommandLine (false)
  46. {
  47. }
  48. void ProjucerApplication::initialise (const String& commandLine)
  49. {
  50. if (commandLine.trimStart().startsWith ("--server"))
  51. {
  52. initialiseLogger ("Compiler_Log_");
  53. LookAndFeel::setDefaultLookAndFeel (&lookAndFeel);
  54. #if JUCE_MAC
  55. Process::setDockIconVisible (false);
  56. #endif
  57. server = createClangServer (commandLine);
  58. }
  59. else
  60. {
  61. initialiseLogger ("IDE_Log_");
  62. Logger::writeToLog (SystemStats::getOperatingSystemName());
  63. Logger::writeToLog ("CPU: " + String (SystemStats::getCpuSpeedInMegaherz())
  64. + "MHz Cores: " + String (SystemStats::getNumCpus())
  65. + " " + String (SystemStats::getMemorySizeInMegabytes()) + "MB");
  66. initialiseBasics();
  67. isRunningCommandLine = commandLine.isNotEmpty();
  68. licenseController = new LicenseController;
  69. licenseController->addLicenseStatusChangedCallback (this);
  70. if (isRunningCommandLine)
  71. {
  72. const int appReturnCode = performCommandLine (commandLine);
  73. if (appReturnCode != commandLineNotPerformed)
  74. {
  75. setApplicationReturnValue (appReturnCode);
  76. quit();
  77. return;
  78. }
  79. isRunningCommandLine = false;
  80. }
  81. if (sendCommandLineToPreexistingInstance())
  82. {
  83. DBG ("Another instance is running - quitting...");
  84. quit();
  85. return;
  86. }
  87. openDocumentManager.registerType (new ProjucerAppClasses::LiveBuildCodeEditorDocument::Type(), 2);
  88. childProcessCache = new ChildProcessCache();
  89. initCommandManager();
  90. menuModel = new MainMenuModel();
  91. settings->appearance.refreshPresetSchemeList();
  92. // do further initialisation in a moment when the message loop has started
  93. triggerAsyncUpdate();
  94. }
  95. }
  96. void ProjucerApplication::initialiseBasics()
  97. {
  98. LookAndFeel::setDefaultLookAndFeel (&lookAndFeel);
  99. settings = new StoredSettings();
  100. ImageCache::setCacheTimeout (30 * 1000);
  101. icons = new Icons();
  102. tooltipWindow.setMillisecondsBeforeTipAppears (1200);
  103. }
  104. bool ProjucerApplication::initialiseLogger (const char* filePrefix)
  105. {
  106. if (logger == nullptr)
  107. {
  108. #if JUCE_LINUX
  109. String folder = "~/.config/Projucer/Logs";
  110. #else
  111. String folder = "com.juce.projucer";
  112. #endif
  113. logger = FileLogger::createDateStampedLogger (folder, filePrefix, ".txt",
  114. getApplicationName() + " " + getApplicationVersion()
  115. + " --- Build date: " __DATE__);
  116. Logger::setCurrentLogger (logger);
  117. }
  118. return logger != nullptr;
  119. }
  120. void ProjucerApplication::handleAsyncUpdate()
  121. {
  122. if (licenseController != nullptr)
  123. licenseController->startWebviewIfNeeded();
  124. #if JUCE_MAC
  125. PopupMenu extraAppleMenuItems;
  126. createExtraAppleMenuItems (extraAppleMenuItems);
  127. // workaround broken "Open Recent" submenu: not passing the
  128. // submenu's title here avoids the defect in JuceMainMenuHandler::addMenuItem
  129. MenuBarModel::setMacMainMenu (menuModel, &extraAppleMenuItems); //, "Open Recent");
  130. #endif
  131. versionChecker = new LatestVersionChecker();
  132. }
  133. void ProjucerApplication::initialiseWindows (const String& commandLine)
  134. {
  135. const String commandLineWithoutNSDebug (commandLine.replace ("-NSDocumentRevisionsDebugMode YES", StringRef()));
  136. if (commandLineWithoutNSDebug.trim().isNotEmpty() && ! commandLineWithoutNSDebug.trim().startsWithChar ('-'))
  137. anotherInstanceStarted (commandLine);
  138. else
  139. mainWindowList.reopenLastProjects();
  140. mainWindowList.createWindowIfNoneAreOpen();
  141. if (licenseController->getState().applicationUsageDataState == LicenseState::ApplicationUsageData::notChosenYet)
  142. showApplicationUsageDataAgreementPopup();
  143. }
  144. void ProjucerApplication::shutdown()
  145. {
  146. if (server != nullptr)
  147. {
  148. destroyClangServer (server);
  149. Logger::writeToLog ("Server shutdown cleanly");
  150. }
  151. versionChecker = nullptr;
  152. appearanceEditorWindow = nullptr;
  153. globalPreferencesWindow = nullptr;
  154. utf8Window = nullptr;
  155. svgPathWindow = nullptr;
  156. aboutWindow = nullptr;
  157. if (licenseController != nullptr)
  158. {
  159. licenseController->removeLicenseStatusChangedCallback (this);
  160. licenseController = nullptr;
  161. }
  162. mainWindowList.forceCloseAllWindows();
  163. openDocumentManager.clear();
  164. childProcessCache = nullptr;
  165. #if JUCE_MAC
  166. MenuBarModel::setMacMainMenu (nullptr);
  167. #endif
  168. menuModel = nullptr;
  169. commandManager = nullptr;
  170. settings = nullptr;
  171. LookAndFeel::setDefaultLookAndFeel (nullptr);
  172. if (! isRunningCommandLine)
  173. Logger::writeToLog ("Shutdown");
  174. deleteLogger();
  175. }
  176. struct AsyncQuitRetrier : private Timer
  177. {
  178. AsyncQuitRetrier() { startTimer (500); }
  179. void timerCallback() override
  180. {
  181. stopTimer();
  182. delete this;
  183. if (JUCEApplicationBase* app = JUCEApplicationBase::getInstance())
  184. app->systemRequestedQuit();
  185. }
  186. JUCE_DECLARE_NON_COPYABLE (AsyncQuitRetrier)
  187. };
  188. void ProjucerApplication::systemRequestedQuit()
  189. {
  190. if (server != nullptr)
  191. {
  192. sendQuitMessageToIDE (server);
  193. }
  194. else if (ModalComponentManager::getInstance()->cancelAllModalComponents())
  195. {
  196. new AsyncQuitRetrier();
  197. }
  198. else
  199. {
  200. if (closeAllMainWindows())
  201. quit();
  202. }
  203. }
  204. //==============================================================================
  205. void ProjucerApplication::licenseStateChanged (const LicenseState& state)
  206. {
  207. #if ! JUCER_ENABLE_GPL_MODE
  208. if (state.type != LicenseState::Type::notLoggedIn
  209. && state.type != LicenseState::Type::noLicenseChosenYet)
  210. #else
  211. ignoreUnused (state);
  212. #endif
  213. {
  214. initialiseWindows (getCommandLineParameters());
  215. }
  216. }
  217. void ProjucerApplication::doLogout()
  218. {
  219. if (licenseController != nullptr)
  220. {
  221. const LicenseState& state = licenseController->getState();
  222. if (state.type != LicenseState::Type::notLoggedIn && closeAllMainWindows())
  223. licenseController->logout();
  224. }
  225. }
  226. //==============================================================================
  227. String ProjucerApplication::getVersionDescription() const
  228. {
  229. String s;
  230. const Time buildDate (Time::getCompilationDate());
  231. s << "Projucer " << ProjectInfo::versionString
  232. << newLine
  233. << "Build date: " << buildDate.getDayOfMonth()
  234. << " " << Time::getMonthName (buildDate.getMonth(), true)
  235. << " " << buildDate.getYear();
  236. return s;
  237. }
  238. void ProjucerApplication::anotherInstanceStarted (const String& commandLine)
  239. {
  240. if (server == nullptr && ! commandLine.trim().startsWithChar ('-'))
  241. openFile (File (commandLine.unquoted()));
  242. }
  243. ProjucerApplication& ProjucerApplication::getApp()
  244. {
  245. ProjucerApplication* const app = dynamic_cast<ProjucerApplication*> (JUCEApplication::getInstance());
  246. jassert (app != nullptr);
  247. return *app;
  248. }
  249. ApplicationCommandManager& ProjucerApplication::getCommandManager()
  250. {
  251. ApplicationCommandManager* cm = ProjucerApplication::getApp().commandManager;
  252. jassert (cm != nullptr);
  253. return *cm;
  254. }
  255. //==============================================================================
  256. enum
  257. {
  258. recentProjectsBaseID = 100,
  259. activeDocumentsBaseID = 300,
  260. colourSchemeBaseID = 1000
  261. };
  262. MenuBarModel* ProjucerApplication::getMenuModel()
  263. {
  264. return menuModel.get();
  265. }
  266. StringArray ProjucerApplication::getMenuNames()
  267. {
  268. const char* const names[] = { "File", "Edit", "View", "Build", "Window", "GUI Editor", "Tools", nullptr };
  269. return StringArray (names);
  270. }
  271. void ProjucerApplication::createMenu (PopupMenu& menu, const String& menuName)
  272. {
  273. if (menuName == "File") createFileMenu (menu);
  274. else if (menuName == "Edit") createEditMenu (menu);
  275. else if (menuName == "View") createViewMenu (menu);
  276. else if (menuName == "Build") createBuildMenu (menu);
  277. else if (menuName == "Window") createWindowMenu (menu);
  278. else if (menuName == "Tools") createToolsMenu (menu);
  279. else if (menuName == "GUI Editor") createGUIEditorMenu (menu);
  280. else jassertfalse; // names have changed?
  281. }
  282. void ProjucerApplication::createFileMenu (PopupMenu& menu)
  283. {
  284. menu.addCommandItem (commandManager, CommandIDs::newProject);
  285. menu.addSeparator();
  286. menu.addCommandItem (commandManager, CommandIDs::open);
  287. PopupMenu recentFiles;
  288. settings->recentFiles.createPopupMenuItems (recentFiles, recentProjectsBaseID, true, true);
  289. menu.addSubMenu ("Open Recent", recentFiles);
  290. menu.addSeparator();
  291. menu.addCommandItem (commandManager, CommandIDs::closeDocument);
  292. menu.addCommandItem (commandManager, CommandIDs::saveDocument);
  293. menu.addCommandItem (commandManager, CommandIDs::saveDocumentAs);
  294. menu.addCommandItem (commandManager, CommandIDs::saveAll);
  295. menu.addSeparator();
  296. menu.addCommandItem (commandManager, CommandIDs::closeProject);
  297. menu.addCommandItem (commandManager, CommandIDs::saveProject);
  298. menu.addSeparator();
  299. menu.addCommandItem (commandManager, CommandIDs::openInIDE);
  300. menu.addCommandItem (commandManager, CommandIDs::saveAndOpenInIDE);
  301. menu.addSeparator();
  302. #if ! JUCER_ENABLE_GPL_MODE
  303. menu.addCommandItem (commandManager, CommandIDs::loginLogout);
  304. #endif
  305. #if ! JUCE_MAC
  306. menu.addCommandItem (commandManager, CommandIDs::showAboutWindow);
  307. menu.addCommandItem (commandManager, CommandIDs::showAppUsageWindow);
  308. menu.addCommandItem (commandManager, CommandIDs::showGlobalPreferences);
  309. menu.addSeparator();
  310. menu.addCommandItem (commandManager, StandardApplicationCommandIDs::quit);
  311. #endif
  312. }
  313. void ProjucerApplication::createEditMenu (PopupMenu& menu)
  314. {
  315. menu.addCommandItem (commandManager, StandardApplicationCommandIDs::undo);
  316. menu.addCommandItem (commandManager, StandardApplicationCommandIDs::redo);
  317. menu.addSeparator();
  318. menu.addCommandItem (commandManager, StandardApplicationCommandIDs::cut);
  319. menu.addCommandItem (commandManager, StandardApplicationCommandIDs::copy);
  320. menu.addCommandItem (commandManager, StandardApplicationCommandIDs::paste);
  321. menu.addCommandItem (commandManager, StandardApplicationCommandIDs::del);
  322. menu.addCommandItem (commandManager, StandardApplicationCommandIDs::selectAll);
  323. menu.addCommandItem (commandManager, StandardApplicationCommandIDs::deselectAll);
  324. menu.addSeparator();
  325. menu.addCommandItem (commandManager, CommandIDs::showFindPanel);
  326. menu.addCommandItem (commandManager, CommandIDs::findSelection);
  327. menu.addCommandItem (commandManager, CommandIDs::findNext);
  328. menu.addCommandItem (commandManager, CommandIDs::findPrevious);
  329. }
  330. void ProjucerApplication::createViewMenu (PopupMenu& menu)
  331. {
  332. menu.addCommandItem (commandManager, CommandIDs::showProjectSettings);
  333. menu.addCommandItem (commandManager, CommandIDs::showProjectTab);
  334. menu.addCommandItem (commandManager, CommandIDs::showBuildTab);
  335. menu.addCommandItem (commandManager, CommandIDs::showFileExplorerPanel);
  336. menu.addCommandItem (commandManager, CommandIDs::showModulesPanel);
  337. menu.addCommandItem (commandManager, CommandIDs::showExportersPanel);
  338. menu.addCommandItem (commandManager, CommandIDs::showExporterSettings);
  339. menu.addSeparator();
  340. createColourSchemeItems (menu);
  341. }
  342. void ProjucerApplication::createBuildMenu (PopupMenu& menu)
  343. {
  344. menu.addCommandItem (commandManager, CommandIDs::toggleBuildEnabled);
  345. menu.addCommandItem (commandManager, CommandIDs::buildNow);
  346. menu.addCommandItem (commandManager, CommandIDs::toggleContinuousBuild);
  347. menu.addSeparator();
  348. menu.addCommandItem (commandManager, CommandIDs::launchApp);
  349. menu.addCommandItem (commandManager, CommandIDs::killApp);
  350. menu.addCommandItem (commandManager, CommandIDs::cleanAll);
  351. menu.addSeparator();
  352. menu.addCommandItem (commandManager, CommandIDs::reinstantiateComp);
  353. menu.addCommandItem (commandManager, CommandIDs::showWarnings);
  354. menu.addSeparator();
  355. menu.addCommandItem (commandManager, CommandIDs::nextError);
  356. menu.addCommandItem (commandManager, CommandIDs::prevError);
  357. }
  358. void ProjucerApplication::createColourSchemeItems (PopupMenu& menu)
  359. {
  360. PopupMenu colourSchemes;
  361. colourSchemes.addItem (colourSchemeBaseID + 0, "Dark");
  362. colourSchemes.addItem (colourSchemeBaseID + 1, "Grey");
  363. colourSchemes.addItem (colourSchemeBaseID + 2, "Light");
  364. menu.addSubMenu ("Colour Scheme", colourSchemes);
  365. }
  366. void ProjucerApplication::createWindowMenu (PopupMenu& menu)
  367. {
  368. menu.addCommandItem (commandManager, CommandIDs::closeWindow);
  369. menu.addSeparator();
  370. menu.addCommandItem (commandManager, CommandIDs::goToPreviousDoc);
  371. menu.addCommandItem (commandManager, CommandIDs::goToNextDoc);
  372. menu.addCommandItem (commandManager, CommandIDs::goToCounterpart);
  373. menu.addSeparator();
  374. const int numDocs = jmin (50, openDocumentManager.getNumOpenDocuments());
  375. for (int i = 0; i < numDocs; ++i)
  376. {
  377. OpenDocumentManager::Document* doc = openDocumentManager.getOpenDocument(i);
  378. menu.addItem (activeDocumentsBaseID + i, doc->getName());
  379. }
  380. menu.addSeparator();
  381. menu.addCommandItem (commandManager, CommandIDs::closeAllDocuments);
  382. }
  383. void ProjucerApplication::createToolsMenu (PopupMenu& menu)
  384. {
  385. menu.addCommandItem (commandManager, CommandIDs::showUTF8Tool);
  386. menu.addCommandItem (commandManager, CommandIDs::showSVGPathTool);
  387. menu.addCommandItem (commandManager, CommandIDs::showTranslationTool);
  388. }
  389. void ProjucerApplication::createExtraAppleMenuItems (PopupMenu& menu)
  390. {
  391. menu.addCommandItem (commandManager, CommandIDs::showAboutWindow);
  392. menu.addCommandItem (commandManager, CommandIDs::showAppUsageWindow);
  393. menu.addSeparator();
  394. menu.addCommandItem (commandManager, CommandIDs::showGlobalPreferences);
  395. }
  396. void ProjucerApplication::handleMainMenuCommand (int menuItemID)
  397. {
  398. if (menuItemID >= recentProjectsBaseID && menuItemID < recentProjectsBaseID + 100)
  399. {
  400. // open a file from the "recent files" menu
  401. openFile (settings->recentFiles.getFile (menuItemID - recentProjectsBaseID));
  402. }
  403. else if (menuItemID >= activeDocumentsBaseID && menuItemID < activeDocumentsBaseID + 200)
  404. {
  405. if (OpenDocumentManager::Document* doc = openDocumentManager.getOpenDocument (menuItemID - activeDocumentsBaseID))
  406. mainWindowList.openDocument (doc, true);
  407. else
  408. jassertfalse;
  409. }
  410. else if (menuItemID >= colourSchemeBaseID && menuItemID < colourSchemeBaseID + 3)
  411. {
  412. auto& appearanceSettings = getAppSettings().appearance;
  413. if (menuItemID == colourSchemeBaseID)
  414. {
  415. lookAndFeel.setColourScheme (LookAndFeel_V4::getDarkColourScheme());
  416. appearanceSettings.selectPresetScheme (0);
  417. }
  418. else if (menuItemID == colourSchemeBaseID + 1)
  419. {
  420. lookAndFeel.setColourScheme (LookAndFeel_V4::getGreyColourScheme());
  421. appearanceSettings.selectPresetScheme (0);
  422. }
  423. else if (menuItemID == colourSchemeBaseID + 2)
  424. {
  425. lookAndFeel.setColourScheme (LookAndFeel_V4::getLightColourScheme());
  426. appearanceSettings.selectPresetScheme (1);
  427. }
  428. lookAndFeel.setupColours();
  429. mainWindowList.sendLookAndFeelChange();
  430. if (utf8Window != nullptr) utf8Window->sendLookAndFeelChange();
  431. if (svgPathWindow != nullptr) svgPathWindow->sendLookAndFeelChange();
  432. if (globalPreferencesWindow != nullptr) globalPreferencesWindow->sendLookAndFeelChange();
  433. if (aboutWindow != nullptr) aboutWindow->sendLookAndFeelChange();
  434. if (applicationUsageDataWindow != nullptr) applicationUsageDataWindow->sendLookAndFeelChange();
  435. }
  436. else
  437. {
  438. handleGUIEditorMenuCommand (menuItemID);
  439. }
  440. }
  441. //==============================================================================
  442. void ProjucerApplication::getAllCommands (Array <CommandID>& commands)
  443. {
  444. JUCEApplication::getAllCommands (commands);
  445. const CommandID ids[] = { CommandIDs::newProject,
  446. CommandIDs::open,
  447. CommandIDs::closeAllDocuments,
  448. CommandIDs::saveAll,
  449. CommandIDs::showGlobalPreferences,
  450. CommandIDs::showUTF8Tool,
  451. CommandIDs::showSVGPathTool,
  452. CommandIDs::showAboutWindow,
  453. CommandIDs::showAppUsageWindow,
  454. CommandIDs::loginLogout };
  455. commands.addArray (ids, numElementsInArray (ids));
  456. }
  457. void ProjucerApplication::getCommandInfo (CommandID commandID, ApplicationCommandInfo& result)
  458. {
  459. switch (commandID)
  460. {
  461. case CommandIDs::newProject:
  462. result.setInfo ("New Project...", "Creates a new Jucer project", CommandCategories::general, 0);
  463. result.defaultKeypresses.add (KeyPress ('n', ModifierKeys::commandModifier, 0));
  464. break;
  465. case CommandIDs::open:
  466. result.setInfo ("Open...", "Opens a Jucer project", CommandCategories::general, 0);
  467. result.defaultKeypresses.add (KeyPress ('o', ModifierKeys::commandModifier, 0));
  468. break;
  469. case CommandIDs::showGlobalPreferences:
  470. result.setInfo ("Preferences...", "Shows the preferences window.", CommandCategories::general, 0);
  471. result.defaultKeypresses.add (KeyPress (',', ModifierKeys::commandModifier, 0));
  472. break;
  473. case CommandIDs::closeAllDocuments:
  474. result.setInfo ("Close All Documents", "Closes all open documents", CommandCategories::general, 0);
  475. result.setActive (openDocumentManager.getNumOpenDocuments() > 0);
  476. break;
  477. case CommandIDs::saveAll:
  478. result.setInfo ("Save All", "Saves all open documents", CommandCategories::general, 0);
  479. result.defaultKeypresses.add (KeyPress ('s', ModifierKeys::commandModifier | ModifierKeys::altModifier, 0));
  480. break;
  481. case CommandIDs::showUTF8Tool:
  482. result.setInfo ("UTF-8 String-Literal Helper", "Shows the UTF-8 string literal utility", CommandCategories::general, 0);
  483. break;
  484. case CommandIDs::showSVGPathTool:
  485. result.setInfo ("SVG Path Converter", "Shows the SVG->Path data conversion utility", CommandCategories::general, 0);
  486. break;
  487. case CommandIDs::showAboutWindow:
  488. result.setInfo ("About Projucer", "Shows the Projucer's 'About' page.", CommandCategories::general, 0);
  489. break;
  490. case CommandIDs::showAppUsageWindow:
  491. result.setInfo ("Application Usage Data", "Shows the application usage data agreement window", CommandCategories::general, 0);
  492. break;
  493. case CommandIDs::loginLogout:
  494. {
  495. bool isLoggedIn = false;
  496. String username;
  497. if (licenseController != nullptr)
  498. {
  499. const LicenseState state = licenseController->getState();
  500. isLoggedIn = (state.type != LicenseState::Type::notLoggedIn && state.type != LicenseState::Type::GPL);
  501. username = state.username;
  502. }
  503. result.setInfo (isLoggedIn
  504. ? String ("Sign out ") + username + "..."
  505. : String ("Sign in..."),
  506. "Log out of your JUCE account", CommandCategories::general, 0);
  507. }
  508. break;
  509. default:
  510. JUCEApplication::getCommandInfo (commandID, result);
  511. break;
  512. }
  513. }
  514. bool ProjucerApplication::perform (const InvocationInfo& info)
  515. {
  516. switch (info.commandID)
  517. {
  518. case CommandIDs::newProject: createNewProject(); break;
  519. case CommandIDs::open: askUserToOpenFile(); break;
  520. case CommandIDs::saveAll: openDocumentManager.saveAll(); break;
  521. case CommandIDs::closeAllDocuments: closeAllDocuments (true); break;
  522. case CommandIDs::showUTF8Tool: showUTF8ToolWindow(); break;
  523. case CommandIDs::showSVGPathTool: showSVGPathDataToolWindow(); break;
  524. case CommandIDs::showGlobalPreferences: AppearanceSettings::showGlobalPreferences (globalPreferencesWindow); break;
  525. case CommandIDs::showAboutWindow: showAboutWindow(); break;
  526. case CommandIDs::showAppUsageWindow: showApplicationUsageDataAgreementPopup(); break;
  527. case CommandIDs::loginLogout: doLogout(); break;
  528. default: return JUCEApplication::perform (info);
  529. }
  530. return true;
  531. }
  532. //==============================================================================
  533. void ProjucerApplication::createNewProject()
  534. {
  535. MainWindow* mw = mainWindowList.getOrCreateEmptyWindow();
  536. mw->showNewProjectWizard();
  537. mainWindowList.avoidSuperimposedWindows (mw);
  538. }
  539. void ProjucerApplication::updateNewlyOpenedProject (Project& p)
  540. {
  541. LiveBuildProjectSettings::updateNewlyOpenedProject (p);
  542. }
  543. void ProjucerApplication::askUserToOpenFile()
  544. {
  545. FileChooser fc ("Open File");
  546. if (fc.browseForFileToOpen())
  547. openFile (fc.getResult());
  548. }
  549. bool ProjucerApplication::openFile (const File& file)
  550. {
  551. return mainWindowList.openFile (file);
  552. }
  553. bool ProjucerApplication::closeAllDocuments (bool askUserToSave)
  554. {
  555. return openDocumentManager.closeAll (askUserToSave);
  556. }
  557. bool ProjucerApplication::closeAllMainWindows()
  558. {
  559. return server != nullptr || mainWindowList.askAllWindowsToClose();
  560. }
  561. //==============================================================================
  562. void ProjucerApplication::showUTF8ToolWindow()
  563. {
  564. if (utf8Window != nullptr)
  565. utf8Window->toFront (true);
  566. else
  567. new FloatingToolWindow ("UTF-8 String Literal Converter",
  568. "utf8WindowPos",
  569. new UTF8Component(), utf8Window, true,
  570. 500, 500, 300, 300, 1000, 1000);
  571. }
  572. void ProjucerApplication::showSVGPathDataToolWindow()
  573. {
  574. if (svgPathWindow != nullptr)
  575. svgPathWindow->toFront (true);
  576. else
  577. new FloatingToolWindow ("SVG Path Converter",
  578. "svgPathWindowPos",
  579. new SVGPathDataComponent(), svgPathWindow, true,
  580. 500, 500, 300, 300, 1000, 1000);
  581. }
  582. void ProjucerApplication::showAboutWindow()
  583. {
  584. if (aboutWindow != nullptr)
  585. aboutWindow->toFront (true);
  586. else
  587. new FloatingToolWindow ({}, {}, new AboutWindowComponent(),
  588. aboutWindow, false,
  589. 500, 300, 500, 300, 500, 300);
  590. }
  591. void ProjucerApplication::showApplicationUsageDataAgreementPopup()
  592. {
  593. if (applicationUsageDataWindow != nullptr)
  594. applicationUsageDataWindow->toFront (true);
  595. else
  596. new FloatingToolWindow ("Application Usage Analytics",
  597. {}, new ApplicationUsageDataWindowComponent (isPaidOrGPL()),
  598. applicationUsageDataWindow, false,
  599. 400, 300, 400, 300, 400, 300);
  600. }
  601. void ProjucerApplication::dismissApplicationUsageDataAgreementPopup()
  602. {
  603. if (applicationUsageDataWindow != nullptr)
  604. applicationUsageDataWindow = nullptr;
  605. }
  606. //==============================================================================
  607. struct FileWithTime
  608. {
  609. FileWithTime (const File& f) : file (f), time (f.getLastModificationTime()) {}
  610. FileWithTime() {}
  611. bool operator< (const FileWithTime& other) const { return time < other.time; }
  612. bool operator== (const FileWithTime& other) const { return time == other.time; }
  613. File file;
  614. Time time;
  615. };
  616. void ProjucerApplication::deleteLogger()
  617. {
  618. const int maxNumLogFilesToKeep = 50;
  619. Logger::setCurrentLogger (nullptr);
  620. if (logger != nullptr)
  621. {
  622. Array<File> logFiles;
  623. logger->getLogFile().getParentDirectory().findChildFiles (logFiles, File::findFiles, false);
  624. if (logFiles.size() > maxNumLogFilesToKeep)
  625. {
  626. Array <FileWithTime> files;
  627. for (int i = 0; i < logFiles.size(); ++i)
  628. files.addUsingDefaultSort (logFiles.getReference(i));
  629. for (int i = 0; i < files.size() - maxNumLogFilesToKeep; ++i)
  630. files.getReference(i).file.deleteFile();
  631. }
  632. }
  633. logger = nullptr;
  634. }
  635. PropertiesFile::Options ProjucerApplication::getPropertyFileOptionsFor (const String& filename)
  636. {
  637. PropertiesFile::Options options;
  638. options.applicationName = filename;
  639. options.filenameSuffix = "settings";
  640. options.osxLibrarySubFolder = "Application Support";
  641. #if JUCE_LINUX
  642. options.folderName = "~/.config/Projucer";
  643. #else
  644. options.folderName = "Projucer";
  645. #endif
  646. return options;
  647. }
  648. void ProjucerApplication::updateAllBuildTabs()
  649. {
  650. for (int i = 0; i < mainWindowList.windows.size(); ++i)
  651. if (ProjectContentComponent* p = mainWindowList.windows.getUnchecked(i)->getProjectContentComponent())
  652. p->rebuildProjectTabs();
  653. }
  654. void ProjucerApplication::initCommandManager()
  655. {
  656. commandManager = new ApplicationCommandManager();
  657. commandManager->registerAllCommandsForTarget (this);
  658. {
  659. CodeDocument doc;
  660. CppCodeEditorComponent ed (File(), doc);
  661. commandManager->registerAllCommandsForTarget (&ed);
  662. }
  663. registerGUIEditorCommands();
  664. }