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.

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