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.

778 lines
31KB

  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. #include <typeinfo>
  20. #include "JuceDemoHeader.h"
  21. //==============================================================================
  22. struct AlphabeticDemoSorter
  23. {
  24. static int compareElements (const JuceDemoTypeBase* first, const JuceDemoTypeBase* second)
  25. {
  26. return first->name.compare (second->name);
  27. }
  28. };
  29. JuceDemoTypeBase::JuceDemoTypeBase (const String& demoName) : name (demoName)
  30. {
  31. AlphabeticDemoSorter sorter;
  32. getDemoTypeList().addSorted (sorter, this);
  33. }
  34. JuceDemoTypeBase::~JuceDemoTypeBase()
  35. {
  36. getDemoTypeList().removeFirstMatchingValue (this);
  37. }
  38. Array<JuceDemoTypeBase*>& JuceDemoTypeBase::getDemoTypeList()
  39. {
  40. static Array<JuceDemoTypeBase*> list;
  41. return list;
  42. }
  43. //==============================================================================
  44. #if JUCE_WINDOWS || JUCE_LINUX || JUCE_MAC
  45. // Just add a simple icon to the Window system tray area or Mac menu bar..
  46. struct DemoTaskbarComponent : public SystemTrayIconComponent,
  47. private Timer
  48. {
  49. DemoTaskbarComponent()
  50. {
  51. setIconImage (ImageCache::getFromMemory (BinaryData::juce_icon_png, BinaryData::juce_icon_pngSize));
  52. setIconTooltip ("JUCE Demo App!");
  53. }
  54. void mouseDown (const MouseEvent&) override
  55. {
  56. // On OSX, there can be problems launching a menu when we're not the foreground
  57. // process, so just in case, we'll first make our process active, and then use a
  58. // timer to wait a moment before opening our menu, which gives the OS some time to
  59. // get its act together and bring our windows to the front.
  60. Process::makeForegroundProcess();
  61. startTimer (50);
  62. }
  63. // This is invoked when the menu is clicked or dismissed
  64. static void menuInvocationCallback (int chosenItemID, DemoTaskbarComponent*)
  65. {
  66. if (chosenItemID == 1)
  67. JUCEApplication::getInstance()->systemRequestedQuit();
  68. }
  69. void timerCallback() override
  70. {
  71. stopTimer();
  72. PopupMenu m;
  73. m.addItem (1, "Quit the JUCE demo");
  74. // It's always better to open menus asynchronously when possible.
  75. m.showMenuAsync (PopupMenu::Options(),
  76. ModalCallbackFunction::forComponent (menuInvocationCallback, this));
  77. }
  78. };
  79. #endif
  80. bool juceDemoRepaintDebuggingActive = false;
  81. //==============================================================================
  82. class ContentComponent : public Component,
  83. public ListBoxModel,
  84. public ApplicationCommandTarget
  85. {
  86. public:
  87. ContentComponent()
  88. {
  89. // set lookAndFeel colour properties
  90. lookAndFeelV3.setColour (Label::textColourId, Colours::white);
  91. lookAndFeelV3.setColour (Label::textColourId, Colours::white);
  92. lookAndFeelV3.setColour (ToggleButton::textColourId, Colours::white);
  93. LookAndFeel::setDefaultLookAndFeel (&lookAndFeelV4);
  94. demoList.setModel (this);
  95. updateDemoListColours();
  96. demoList.selectRow (0);
  97. if (Desktop::getInstance().getMainMouseSource().isTouch())
  98. demoList.getViewport()->setScrollOnDragEnabled (true);
  99. addAndMakeVisible (demoList);
  100. addAndMakeVisible (sidePanel);
  101. sidePanel.setAlwaysOnTop (true);
  102. }
  103. ~ContentComponent()
  104. {
  105. // before deleting our lookandfeel object, make sure it's no longer in use
  106. LookAndFeel::setDefaultLookAndFeel (nullptr);
  107. }
  108. void clearCurrentDemo()
  109. {
  110. currentDemo.reset();
  111. }
  112. void resized() override
  113. {
  114. auto r = getLocalBounds();
  115. if (r.getWidth() > 600)
  116. {
  117. demoList.setBounds (r.removeFromLeft (210));
  118. demoList.setRowHeight (20);
  119. }
  120. else
  121. {
  122. demoList.setBounds (r.removeFromLeft (130));
  123. demoList.setRowHeight (30);
  124. }
  125. if (currentDemo != nullptr)
  126. currentDemo->setBounds (r);
  127. }
  128. int getNumRows() override
  129. {
  130. return JuceDemoTypeBase::getDemoTypeList().size();
  131. }
  132. void paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected) override
  133. {
  134. if (rowIsSelected)
  135. g.fillAll (Colours::deepskyblue);
  136. if (auto* type = JuceDemoTypeBase::getDemoTypeList() [rowNumber])
  137. {
  138. auto name = type->name.trimCharactersAtStart ("0123456789").trimStart();
  139. AttributedString a;
  140. a.setJustification (Justification::centredLeft);
  141. String category;
  142. if (name.containsChar (':'))
  143. {
  144. category = name.upToFirstOccurrenceOf (":", true, false);
  145. name = name.fromFirstOccurrenceOf (":", false, false).trim();
  146. if (height > 20)
  147. category << "\n";
  148. else
  149. category << " ";
  150. }
  151. auto categoryColour = demoList.findColour (ListBox::outlineColourId);
  152. auto nameColour = demoList.findColour (ListBox::textColourId);
  153. if (category.isNotEmpty())
  154. a.append (category, Font (10.0f), categoryColour);
  155. a.append (name, Font (13.0f), nameColour);
  156. a.draw (g, Rectangle<int> (width + 10, height).reduced (6, 0).toFloat());
  157. }
  158. }
  159. void selectedRowsChanged (int lastRowSelected) override
  160. {
  161. if (auto* selectedDemoType = JuceDemoTypeBase::getDemoTypeList() [lastRowSelected])
  162. {
  163. currentDemo.reset();
  164. addAndMakeVisible (currentDemo = selectedDemoType->createComponent());
  165. currentDemo->setName (selectedDemoType->name);
  166. resized();
  167. }
  168. }
  169. MouseCursor getMouseCursorForRow (int /*row*/) override
  170. {
  171. return MouseCursor::PointingHandCursor;
  172. }
  173. int getCurrentPageIndex() const noexcept
  174. {
  175. if (currentDemo == nullptr)
  176. return -1;
  177. auto& demos = JuceDemoTypeBase::getDemoTypeList();
  178. for (int i = demos.size(); --i >= 0;)
  179. if (demos.getUnchecked (i)->name == currentDemo->getName())
  180. return i;
  181. return -1;
  182. }
  183. void moveDemoPages (int numPagesToMove)
  184. {
  185. demoList.selectRow (negativeAwareModulo (getCurrentPageIndex() + numPagesToMove,
  186. JuceDemoTypeBase::getDemoTypeList().size()));
  187. }
  188. bool isShowingOpenGLDemo() const
  189. {
  190. return currentDemo != nullptr
  191. && currentDemo->getName().contains ("OpenGL")
  192. && ! isShowingOpenGL2DDemo();
  193. }
  194. bool isShowingOpenGL2DDemo() const
  195. {
  196. return currentDemo != nullptr && currentDemo->getName().contains ("OpenGL 2D");
  197. }
  198. SidePanel& getSharedSidePanel()
  199. {
  200. return sidePanel;
  201. }
  202. private:
  203. ListBox demoList;
  204. ScopedPointer<Component> currentDemo;
  205. SidePanel sidePanel {"Menu", 300, false};
  206. LookAndFeel_V1 lookAndFeelV1;
  207. LookAndFeel_V2 lookAndFeelV2;
  208. LookAndFeel_V3 lookAndFeelV3;
  209. LookAndFeel_V4 lookAndFeelV4;
  210. //==============================================================================
  211. // The following methods implement the ApplicationCommandTarget interface, allowing
  212. // this window to publish a set of actions it can perform, and which can be mapped
  213. // onto menus, keypresses, etc.
  214. ApplicationCommandTarget* getNextCommandTarget() override
  215. {
  216. // this will return the next parent component that is an ApplicationCommandTarget (in this
  217. // case, there probably isn't one, but it's best to use this method in your own apps).
  218. return findFirstTargetParentComponent();
  219. }
  220. void getAllCommands (Array<CommandID>& commands) override
  221. {
  222. // this returns the set of all commands that this target can perform..
  223. const CommandID ids[] = { MainAppWindow::showPreviousDemo,
  224. MainAppWindow::showNextDemo,
  225. MainAppWindow::welcome,
  226. MainAppWindow::componentsAnimation,
  227. MainAppWindow::componentsDialogBoxes,
  228. MainAppWindow::componentsKeyMappings,
  229. MainAppWindow::componentsMDI,
  230. MainAppWindow::componentsPropertyEditors,
  231. MainAppWindow::componentsTransforms,
  232. MainAppWindow::componentsWebBrowsers,
  233. MainAppWindow::componentsWidgets,
  234. MainAppWindow::useLookAndFeelV1,
  235. MainAppWindow::useLookAndFeelV2,
  236. MainAppWindow::useLookAndFeelV3,
  237. MainAppWindow::useLookAndFeelV4Dark,
  238. MainAppWindow::useLookAndFeelV4Midnight,
  239. MainAppWindow::useLookAndFeelV4Grey,
  240. MainAppWindow::useLookAndFeelV4Light,
  241. MainAppWindow::toggleRepaintDebugging,
  242. #if ! JUCE_LINUX
  243. MainAppWindow::goToKioskMode,
  244. #endif
  245. MainAppWindow::useNativeTitleBar
  246. };
  247. commands.addArray (ids, numElementsInArray (ids));
  248. const CommandID engineIDs[] = { MainAppWindow::renderingEngineOne,
  249. MainAppWindow::renderingEngineTwo,
  250. MainAppWindow::renderingEngineThree };
  251. auto renderingEngines = MainAppWindow::getMainAppWindow()->getRenderingEngines();
  252. commands.addArray (engineIDs, renderingEngines.size());
  253. }
  254. void getCommandInfo (CommandID commandID, ApplicationCommandInfo& result) override
  255. {
  256. const String generalCategory ("General");
  257. const String demosCategory ("Demos");
  258. switch (commandID)
  259. {
  260. case MainAppWindow::showPreviousDemo:
  261. result.setInfo ("Previous Demo", "Shows the previous demo in the list", demosCategory, 0);
  262. result.addDefaultKeypress ('-', ModifierKeys::commandModifier);
  263. break;
  264. case MainAppWindow::showNextDemo:
  265. result.setInfo ("Next Demo", "Shows the next demo in the list", demosCategory, 0);
  266. result.addDefaultKeypress ('=', ModifierKeys::commandModifier);
  267. break;
  268. case MainAppWindow::welcome:
  269. result.setInfo ("Welcome Demo", "Shows the 'Welcome' demo", demosCategory, 0);
  270. result.addDefaultKeypress ('1', ModifierKeys::commandModifier);
  271. break;
  272. case MainAppWindow::componentsAnimation:
  273. result.setInfo ("Animation Demo", "Shows the 'Animation' demo", demosCategory, 0);
  274. result.addDefaultKeypress ('2', ModifierKeys::commandModifier);
  275. break;
  276. case MainAppWindow::componentsDialogBoxes:
  277. result.setInfo ("Dialog Boxes Demo", "Shows the 'Dialog Boxes' demo", demosCategory, 0);
  278. result.addDefaultKeypress ('3', ModifierKeys::commandModifier);
  279. break;
  280. case MainAppWindow::componentsKeyMappings:
  281. result.setInfo ("Key Mappings Demo", "Shows the 'Key Mappings' demo", demosCategory, 0);
  282. result.addDefaultKeypress ('4', ModifierKeys::commandModifier);
  283. break;
  284. case MainAppWindow::componentsMDI:
  285. result.setInfo ("Multi-Document Demo", "Shows the 'Multi-Document' demo", demosCategory, 0);
  286. result.addDefaultKeypress ('5', ModifierKeys::commandModifier);
  287. break;
  288. case MainAppWindow::componentsPropertyEditors:
  289. result.setInfo ("Property Editor Demo", "Shows the 'Property Editor' demo", demosCategory, 0);
  290. result.addDefaultKeypress ('6', ModifierKeys::commandModifier);
  291. break;
  292. case MainAppWindow::componentsTransforms:
  293. result.setInfo ("Component Transforms Demo", "Shows the 'Transforms' demo", demosCategory, 0);
  294. result.addDefaultKeypress ('7', ModifierKeys::commandModifier);
  295. break;
  296. case MainAppWindow::componentsWebBrowsers:
  297. result.setInfo ("Web Browser Demo", "Shows the 'Web Browser' demo", demosCategory, 0);
  298. result.addDefaultKeypress ('8', ModifierKeys::commandModifier);
  299. break;
  300. case MainAppWindow::componentsWidgets:
  301. result.setInfo ("Widgets Demo", "Shows the 'Widgets' demo", demosCategory, 0);
  302. result.addDefaultKeypress ('9', ModifierKeys::commandModifier);
  303. break;
  304. case MainAppWindow::renderingEngineOne:
  305. case MainAppWindow::renderingEngineTwo:
  306. case MainAppWindow::renderingEngineThree:
  307. {
  308. auto& mainWindow = *MainAppWindow::getMainAppWindow();
  309. auto engines = mainWindow.getRenderingEngines();
  310. const int index = commandID - MainAppWindow::renderingEngineOne;
  311. result.setInfo ("Use " + engines[index], "Uses the " + engines[index] + " engine to render the UI", generalCategory, 0);
  312. result.setTicked (mainWindow.getActiveRenderingEngine() == index);
  313. result.addDefaultKeypress ('1' + index, ModifierKeys::noModifiers);
  314. break;
  315. }
  316. case MainAppWindow::useLookAndFeelV1:
  317. result.setInfo ("Use LookAndFeel_V1", String(), generalCategory, 0);
  318. result.addDefaultKeypress ('i', ModifierKeys::commandModifier);
  319. result.setTicked (isLookAndFeelSelected<LookAndFeel_V1>());
  320. break;
  321. case MainAppWindow::useLookAndFeelV2:
  322. result.setInfo ("Use LookAndFeel_V2", String(), generalCategory, 0);
  323. result.addDefaultKeypress ('o', ModifierKeys::commandModifier);
  324. result.setTicked (isLookAndFeelSelected<LookAndFeel_V2>());
  325. break;
  326. case MainAppWindow::useLookAndFeelV3:
  327. result.setInfo ("Use LookAndFeel_V3", String(), generalCategory, 0);
  328. result.addDefaultKeypress ('p', ModifierKeys::commandModifier);
  329. result.setTicked (isLookAndFeelSelected<LookAndFeel_V3>());
  330. break;
  331. case MainAppWindow::useLookAndFeelV4Dark:
  332. result.setInfo ("Use LookAndFeel_V4 Dark", String(), generalCategory, 0);
  333. result.addDefaultKeypress ('k', ModifierKeys::commandModifier);
  334. result.setTicked (isColourSchemeActive (LookAndFeel_V4::getDarkColourScheme()));
  335. break;
  336. case MainAppWindow::useLookAndFeelV4Midnight:
  337. result.setInfo ("Use LookAndFeel_V4 Midnight", String(), generalCategory, 0);
  338. result.setTicked (isColourSchemeActive (LookAndFeel_V4::getMidnightColourScheme()));
  339. break;
  340. case MainAppWindow::useLookAndFeelV4Grey:
  341. result.setInfo ("Use LookAndFeel_V4 Grey", String(), generalCategory, 0);
  342. result.setTicked (isColourSchemeActive (LookAndFeel_V4::getGreyColourScheme()));
  343. break;
  344. case MainAppWindow::useLookAndFeelV4Light:
  345. result.setInfo ("Use LookAndFeel_V4 Light", String(), generalCategory, 0);
  346. result.setTicked (isColourSchemeActive (LookAndFeel_V4::getLightColourScheme()));
  347. break;
  348. case MainAppWindow::toggleRepaintDebugging:
  349. result.setInfo ("Toggle repaint display", String(), generalCategory, 0);
  350. result.addDefaultKeypress ('r', ModifierKeys());
  351. result.setTicked (juceDemoRepaintDebuggingActive);
  352. break;
  353. case MainAppWindow::useNativeTitleBar:
  354. {
  355. result.setInfo ("Use native window title bar", String(), generalCategory, 0);
  356. result.addDefaultKeypress ('n', ModifierKeys::commandModifier);
  357. bool nativeTitlebar = false;
  358. if (auto* mainWindow = MainAppWindow::getMainAppWindow())
  359. nativeTitlebar = mainWindow->isUsingNativeTitleBar();
  360. result.setTicked (nativeTitlebar);
  361. break;
  362. }
  363. #if ! JUCE_LINUX
  364. case MainAppWindow::goToKioskMode:
  365. result.setInfo ("Show full-screen kiosk mode", String(), generalCategory, 0);
  366. result.addDefaultKeypress ('f', ModifierKeys::commandModifier);
  367. result.setTicked (Desktop::getInstance().getKioskModeComponent() != 0);
  368. break;
  369. #endif
  370. default:
  371. break;
  372. }
  373. }
  374. bool perform (const InvocationInfo& info) override
  375. {
  376. if (auto* mainWindow = MainAppWindow::getMainAppWindow())
  377. {
  378. switch (info.commandID)
  379. {
  380. case MainAppWindow::showPreviousDemo: moveDemoPages (-1); break;
  381. case MainAppWindow::showNextDemo: moveDemoPages ( 1); break;
  382. case MainAppWindow::welcome:
  383. case MainAppWindow::componentsAnimation:
  384. case MainAppWindow::componentsDialogBoxes:
  385. case MainAppWindow::componentsKeyMappings:
  386. case MainAppWindow::componentsMDI:
  387. case MainAppWindow::componentsPropertyEditors:
  388. case MainAppWindow::componentsTransforms:
  389. case MainAppWindow::componentsWebBrowsers:
  390. case MainAppWindow::componentsWidgets:
  391. demoList.selectRow (info.commandID - MainAppWindow::welcome);
  392. break;
  393. case MainAppWindow::renderingEngineOne:
  394. case MainAppWindow::renderingEngineTwo:
  395. case MainAppWindow::renderingEngineThree:
  396. mainWindow->setRenderingEngine (info.commandID - MainAppWindow::renderingEngineOne);
  397. break;
  398. case MainAppWindow::useLookAndFeelV1:
  399. LookAndFeel::setDefaultLookAndFeel (&lookAndFeelV1);
  400. updateDemoListColours();
  401. break;
  402. case MainAppWindow::useLookAndFeelV2:
  403. LookAndFeel::setDefaultLookAndFeel (&lookAndFeelV2);
  404. updateDemoListColours();
  405. break;
  406. case MainAppWindow::useLookAndFeelV3:
  407. LookAndFeel::setDefaultLookAndFeel (&lookAndFeelV3);
  408. updateDemoListColours();
  409. break;
  410. case MainAppWindow::useLookAndFeelV4Dark:
  411. lookAndFeelV4.setColourScheme (LookAndFeel_V4::getDarkColourScheme());
  412. LookAndFeel::setDefaultLookAndFeel (&lookAndFeelV4);
  413. updateDemoListColours();
  414. break;
  415. case MainAppWindow::useLookAndFeelV4Midnight:
  416. lookAndFeelV4.setColourScheme (LookAndFeel_V4::getMidnightColourScheme());
  417. LookAndFeel::setDefaultLookAndFeel (&lookAndFeelV4);
  418. updateDemoListColours();
  419. break;
  420. case MainAppWindow::useLookAndFeelV4Grey:
  421. lookAndFeelV4.setColourScheme (LookAndFeel_V4::getGreyColourScheme());
  422. LookAndFeel::setDefaultLookAndFeel (&lookAndFeelV4);
  423. updateDemoListColours();
  424. break;
  425. case MainAppWindow::useLookAndFeelV4Light:
  426. lookAndFeelV4.setColourScheme (LookAndFeel_V4::getLightColourScheme());
  427. LookAndFeel::setDefaultLookAndFeel (&lookAndFeelV4);
  428. updateDemoListColours();
  429. break;
  430. case MainAppWindow::toggleRepaintDebugging:
  431. juceDemoRepaintDebuggingActive = ! juceDemoRepaintDebuggingActive;
  432. mainWindow->repaint();
  433. break;
  434. case MainAppWindow::useNativeTitleBar:
  435. mainWindow->setUsingNativeTitleBar (! mainWindow->isUsingNativeTitleBar());
  436. break;
  437. #if ! JUCE_LINUX
  438. case MainAppWindow::goToKioskMode:
  439. {
  440. auto& desktop = Desktop::getInstance();
  441. if (desktop.getKioskModeComponent() == nullptr)
  442. desktop.setKioskModeComponent (getTopLevelComponent());
  443. else
  444. desktop.setKioskModeComponent (nullptr);
  445. break;
  446. }
  447. #endif
  448. default:
  449. return false;
  450. }
  451. }
  452. return true;
  453. }
  454. template <typename LookAndFeelType>
  455. bool isLookAndFeelSelected()
  456. {
  457. LookAndFeel& lf = getLookAndFeel();
  458. return typeid (LookAndFeelType) == typeid (lf);
  459. }
  460. bool isColourSchemeActive (LookAndFeel_V4::ColourScheme scheme)
  461. {
  462. if (auto* v4 = dynamic_cast<LookAndFeel_V4*> (&LookAndFeel::getDefaultLookAndFeel()))
  463. if (v4->getCurrentColourScheme() == scheme)
  464. return true;
  465. return false;
  466. }
  467. void updateDemoListColours()
  468. {
  469. demoList.setColour (ListBox::backgroundColourId,
  470. getUIColourIfAvailable (LookAndFeel_V4::ColourScheme::UIColour::widgetBackground, Colour::greyLevel (0.2f)));
  471. demoList.setColour (ListBox::textColourId,
  472. getUIColourIfAvailable (LookAndFeel_V4::ColourScheme::UIColour::defaultText,
  473. Colours::white.withAlpha (0.9f)));
  474. demoList.setColour (ListBox::outlineColourId,
  475. getUIColourIfAvailable (LookAndFeel_V4::ColourScheme::UIColour::defaultText,
  476. Colour::greyLevel (0.5f)).interpolatedWith (Colours::red, 0.4f));
  477. }
  478. };
  479. //==============================================================================
  480. static ScopedPointer<ApplicationCommandManager> applicationCommandManager;
  481. static ScopedPointer<AudioDeviceManager> sharedAudioDeviceManager;
  482. MainAppWindow::MainAppWindow()
  483. : DocumentWindow (JUCEApplication::getInstance()->getApplicationName(),
  484. LookAndFeel::getDefaultLookAndFeel().findColour (ResizableWindow::backgroundColourId),
  485. DocumentWindow::allButtons)
  486. {
  487. setUsingNativeTitleBar (true);
  488. setResizable (true, false);
  489. setResizeLimits (400, 400, 10000, 10000);
  490. #if JUCE_IOS || JUCE_ANDROID
  491. setFullScreen (true);
  492. #else
  493. setBounds ((int) (0.1f * getParentWidth()),
  494. (int) (0.1f * getParentHeight()),
  495. jmax (850, (int) (0.5f * getParentWidth())),
  496. jmax (600, (int) (0.7f * getParentHeight())));
  497. #endif
  498. contentComponent = new ContentComponent();
  499. setContentNonOwned (contentComponent, false);
  500. setVisible (true);
  501. // this lets the command manager use keypresses that arrive in our window to send out commands
  502. addKeyListener (getApplicationCommandManager().getKeyMappings());
  503. #if JUCE_WINDOWS || JUCE_LINUX || JUCE_MAC
  504. taskbarIcon = new DemoTaskbarComponent();
  505. #endif
  506. #if JUCE_ANDROID
  507. setOpenGLRenderingEngine();
  508. #endif
  509. triggerAsyncUpdate();
  510. }
  511. MainAppWindow::~MainAppWindow()
  512. {
  513. contentComponent->clearCurrentDemo();
  514. clearContentComponent();
  515. contentComponent.reset();
  516. applicationCommandManager.reset();
  517. sharedAudioDeviceManager.reset();
  518. #if JUCE_OPENGL
  519. openGLContext.detach();
  520. #endif
  521. }
  522. void MainAppWindow::closeButtonPressed()
  523. {
  524. JUCEApplication::getInstance()->systemRequestedQuit();
  525. }
  526. ApplicationCommandManager& MainAppWindow::getApplicationCommandManager()
  527. {
  528. if (applicationCommandManager == nullptr)
  529. applicationCommandManager = new ApplicationCommandManager();
  530. return *applicationCommandManager;
  531. }
  532. AudioDeviceManager& MainAppWindow::getSharedAudioDeviceManager()
  533. {
  534. if (sharedAudioDeviceManager == nullptr)
  535. {
  536. sharedAudioDeviceManager = new AudioDeviceManager();
  537. RuntimePermissions::request (RuntimePermissions::recordAudio, runtimePermissionsCallback);
  538. }
  539. return *sharedAudioDeviceManager;
  540. }
  541. void MainAppWindow::runtimePermissionsCallback (bool wasGranted)
  542. {
  543. int numInputChannels = wasGranted ? 2 : 0;
  544. sharedAudioDeviceManager->initialise (numInputChannels, 2, nullptr, true, String(), nullptr);
  545. }
  546. MainAppWindow* MainAppWindow::getMainAppWindow()
  547. {
  548. for (int i = TopLevelWindow::getNumTopLevelWindows(); --i >= 0;)
  549. if (auto* maw = dynamic_cast<MainAppWindow*> (TopLevelWindow::getTopLevelWindow (i)))
  550. return maw;
  551. return nullptr;
  552. }
  553. void MainAppWindow::handleAsyncUpdate()
  554. {
  555. // This registers all of our commands with the command manager but has to be done after the window has
  556. // been created so we can find the number of rendering engines available
  557. auto& commandManager = MainAppWindow::getApplicationCommandManager();
  558. commandManager.registerAllCommandsForTarget (contentComponent);
  559. commandManager.registerAllCommandsForTarget (JUCEApplication::getInstance());
  560. }
  561. void MainAppWindow::showMessageBubble (const String& text)
  562. {
  563. currentBubbleMessage = new BubbleMessageComponent (500);
  564. getContentComponent()->addChildComponent (currentBubbleMessage);
  565. AttributedString attString;
  566. attString.append (text, Font (15.0f));
  567. currentBubbleMessage->showAt ({ getLocalBounds().getCentreX(), 10, 1, 1 },
  568. attString,
  569. 500, // numMillisecondsBeforeRemoving
  570. true, // removeWhenMouseClicked
  571. false); // deleteSelfAfterUse
  572. }
  573. static const char* openGLRendererName = "OpenGL Renderer";
  574. StringArray MainAppWindow::getRenderingEngines() const
  575. {
  576. StringArray renderingEngines;
  577. if (auto* peer = getPeer())
  578. renderingEngines = peer->getAvailableRenderingEngines();
  579. #if JUCE_OPENGL
  580. renderingEngines.add (openGLRendererName);
  581. #endif
  582. return renderingEngines;
  583. }
  584. void MainAppWindow::setRenderingEngine (int index)
  585. {
  586. showMessageBubble (getRenderingEngines()[index]);
  587. #if JUCE_OPENGL
  588. if (getRenderingEngines()[index] == openGLRendererName
  589. && contentComponent != nullptr
  590. && ! contentComponent->isShowingOpenGLDemo())
  591. {
  592. openGLContext.attachTo (*getTopLevelComponent());
  593. return;
  594. }
  595. openGLContext.detach();
  596. #endif
  597. if (auto* peer = getPeer())
  598. peer->setCurrentRenderingEngine (index);
  599. }
  600. void MainAppWindow::setOpenGLRenderingEngine()
  601. {
  602. setRenderingEngine (getRenderingEngines().indexOf (openGLRendererName));
  603. }
  604. int MainAppWindow::getActiveRenderingEngine() const
  605. {
  606. #if JUCE_OPENGL
  607. if (openGLContext.isAttached())
  608. return getRenderingEngines().indexOf (openGLRendererName);
  609. #endif
  610. if (auto* peer = getPeer())
  611. return peer->getCurrentRenderingEngine();
  612. return 0;
  613. }
  614. SidePanel& MainAppWindow::getSharedSidePanel()
  615. {
  616. return getMainAppWindow()->contentComponent->getSharedSidePanel();
  617. }
  618. Path MainAppWindow::getJUCELogoPath()
  619. {
  620. return Drawable::parseSVGPath (
  621. "M250,301.3c-37.2,0-67.5-30.3-67.5-67.5s30.3-67.5,67.5-67.5s67.5,30.3,67.5,67.5S287.2,301.3,250,301.3zM250,170.8c-34.7,0-63,28.3-63,63s28.3,63,63,63s63-28.3,63-63S284.7,170.8,250,170.8z"
  622. "M247.8,180.4c0-2.3-1.8-4.1-4.1-4.1c-0.2,0-0.3,0-0.5,0c-10.6,1.2-20.6,5.4-29,12c-1,0.8-1.5,1.8-1.6,2.9c-0.1,1.2,0.4,2.3,1.3,3.2l32.5,32.5c0.5,0.5,1.4,0.1,1.4-0.6V180.4z"
  623. "M303.2,231.6c1.2,0,2.3-0.4,3.1-1.2c0.9-0.9,1.3-2.1,1.1-3.3c-1.2-10.6-5.4-20.6-12-29c-0.8-1-1.9-1.6-3.2-1.6c-1.1,0-2.1,0.5-3,1.3l-32.5,32.5c-0.5,0.5-0.1,1.4,0.6,1.4L303.2,231.6z"
  624. "M287.4,191.3c-0.1-1.1-0.6-2.2-1.6-2.9c-8.4-6.6-18.4-10.8-29-12c-0.2,0-0.3,0-0.5,0c-2.3,0-4.1,1.9-4.1,4.1v46c0,0.7,0.9,1.1,1.4,0.6l32.5-32.5C287,193.6,287.5,192.5,287.4,191.3z"
  625. "M252.2,287.2c0,2.3,1.8,4.1,4.1,4.1c0.2,0,0.3,0,0.5,0c10.6-1.2,20.6-5.4,29-12c1-0.8,1.5-1.8,1.6-2.9c0.1-1.2-0.4-2.3-1.3-3.2l-32.5-32.5c-0.5-0.5-1.4-0.1-1.4,0.6V287.2z"
  626. "M292.3,271.2L292.3,271.2c1.2,0,2.4-0.6,3.2-1.6c6.6-8.4,10.8-18.4,12-29c0.1-1.2-0.3-2.4-1.1-3.3c-0.8-0.8-1.9-1.2-3.1-1.2l-45.9,0c-0.7,0-1.1,0.9-0.6,1.4l32.5,32.5C290.2,270.8,291.2,271.2,292.3,271.2z"
  627. "M207.7,196.4c-1.2,0-2.4,0.6-3.2,1.6c-6.6,8.4-10.8,18.4-12,29c-0.1,1.2,0.3,2.4,1.1,3.3c0.8,0.8,1.9,1.2,3.1,1.2l45.9,0c0.7,0,1.1-0.9,0.6-1.4l-32.5-32.5C209.8,196.8,208.8,196.4,207.7,196.4z"
  628. "M242.6,236.1l-45.9,0c-1.2,0-2.3,0.4-3.1,1.2c-0.9,0.9-1.3,2.1-1.1,3.3c1.2,10.6,5.4,20.6,12,29c0.8,1,1.9,1.6,3.2,1.6c1.1,0,2.1-0.5,3-1.3c0,0,0,0,0,0l32.5-32.5C243.7,236.9,243.4,236.1,242.6,236.1z"
  629. "M213.8,273.1L213.8,273.1c-0.9,0.9-1.3,2-1.3,3.2c0.1,1.1,0.6,2.2,1.6,2.9c8.4,6.6,18.4,10.8,29,12c0.2,0,0.3,0,0.5,0h0c1.2,0,2.3-0.5,3.1-1.4c0.7-0.8,1-1.8,1-2.9v-45.9c0-0.7-0.9-1.1-1.4-0.6l-13.9,13.9L213.8,273.1z"
  630. "M197.2,353c-4.1,0-7.4-1.5-10.4-5.4l4-3.5c2,2.6,3.9,3.6,6.4,3.6c4.4,0,7.4-3.3,7.4-8.3v-24.7h5.6v24.7C210.2,347.5,204.8,353,197.2,353z"
  631. "M232.4,353c-8.1,0-15-6-15-15.8v-22.5h5.6v22.2c0,6.6,3.9,10.8,9.5,10.8c5.6,0,9.5-4.3,9.5-10.8v-22.2h5.6v22.5C247.5,347,240.5,353,232.4,353z"
  632. "M272,353c-10.8,0-19.5-8.6-19.5-19.3c0-10.8,8.8-19.3,19.5-19.3c4.8,0,9,1.6,12.3,4.4l-3.3,4.1c-3.4-2.4-5.7-3.2-8.9-3.2c-7.7,0-13.8,6.2-13.8,14.1c0,7.9,6.1,14.1,13.8,14.1c3.1,0,5.6-1,8.8-3.2l3.3,4.1C280.1,351.9,276.4,353,272,353z"
  633. "M290.4,352.5v-37.8h22.7v5H296v11.2h16.5v5H296v11.6h17.2v5H290.4z");
  634. }