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.

691 lines
25KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-9 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. #include "jucedemo_headers.h"
  19. #include "MainDemoWindow.h"
  20. //==============================================================================
  21. class ContentComp : public Component,
  22. public MenuBarModel,
  23. public ApplicationCommandTarget
  24. {
  25. public:
  26. //==============================================================================
  27. ContentComp (MainDemoWindow& mainWindow_)
  28. : mainWindow (mainWindow_),
  29. currentDemoId (0)
  30. {
  31. invokeDirectly (showRendering, true);
  32. }
  33. //==============================================================================
  34. void showDemo (Component* demoComp)
  35. {
  36. currentDemo = demoComp;
  37. #if JUCE_OPENGL
  38. if (openGLWrapperComp != nullptr)
  39. openGLWrapperComp->addAndMakeVisible (currentDemo);
  40. else
  41. #endif
  42. addAndMakeVisible (currentDemo);
  43. currentDemo->setBounds ("0, 0, parent.width, parent.height");
  44. }
  45. //==============================================================================
  46. const StringArray getMenuBarNames()
  47. {
  48. const char* const names[] = { "Demo", "Look-and-feel", nullptr };
  49. return StringArray (names);
  50. }
  51. const PopupMenu getMenuForIndex (int menuIndex, const String& /*menuName*/)
  52. {
  53. ApplicationCommandManager* commandManager = &(mainWindow.commandManager);
  54. PopupMenu menu;
  55. if (menuIndex == 0)
  56. {
  57. menu.addCommandItem (commandManager, showRendering);
  58. menu.addCommandItem (commandManager, showFontsAndText);
  59. menu.addCommandItem (commandManager, showWidgets);
  60. menu.addCommandItem (commandManager, showThreading);
  61. menu.addCommandItem (commandManager, showTreeView);
  62. menu.addCommandItem (commandManager, showTable);
  63. menu.addCommandItem (commandManager, showAudio);
  64. menu.addCommandItem (commandManager, showDragAndDrop);
  65. menu.addCommandItem (commandManager, showOpenGL);
  66. menu.addCommandItem (commandManager, showQuicktime);
  67. menu.addCommandItem (commandManager, showDirectShow);
  68. menu.addCommandItem (commandManager, showInterprocessComms);
  69. menu.addCommandItem (commandManager, showCamera);
  70. menu.addCommandItem (commandManager, showWebBrowser);
  71. menu.addCommandItem (commandManager, showCodeEditor);
  72. menu.addSeparator();
  73. menu.addCommandItem (commandManager, StandardApplicationCommandIDs::quit);
  74. }
  75. else if (menuIndex == 1)
  76. {
  77. menu.addCommandItem (commandManager, setDefaultLookAndFeel);
  78. menu.addCommandItem (commandManager, setOldSchoolLookAndFeel);
  79. menu.addSeparator();
  80. menu.addCommandItem (commandManager, useNativeTitleBar);
  81. #if JUCE_MAC
  82. menu.addCommandItem (commandManager, useNativeMenus);
  83. #endif
  84. #if ! JUCE_LINUX
  85. menu.addCommandItem (commandManager, goToKioskMode);
  86. #endif
  87. StringArray engines (getRenderingEngines());
  88. if (engines.size() > 1)
  89. {
  90. menu.addSeparator();
  91. const int currentEngine = openGLWrapperComp != nullptr ? engines.size() - 1
  92. : getPeer()->getCurrentRenderingEngine();
  93. for (int i = 0; i < engines.size(); ++i)
  94. menu.addItem (5001 + i, "Use " + engines[i], true, i == currentEngine);
  95. }
  96. }
  97. return menu;
  98. }
  99. void menuItemSelected (int menuItemID, int /*topLevelMenuIndex*/)
  100. {
  101. // most of our menu items are invoked automatically as commands, but we can handle the
  102. // other special cases here..
  103. if (menuItemID >= 5001 && menuItemID < 5010)
  104. {
  105. const int engineIndex = menuItemID - 5001;
  106. #if JUCE_OPENGL
  107. if (engineIndex >= getPeer()->getAvailableRenderingEngines().size())
  108. {
  109. setUsingOpenGLRenderer (true);
  110. return;
  111. }
  112. #endif
  113. setUsingOpenGLRenderer (false);
  114. getPeer()->setCurrentRenderingEngine (engineIndex);
  115. }
  116. }
  117. void setUsingOpenGLRenderer (bool shouldUseOpenGL)
  118. {
  119. #if JUCE_OPENGL
  120. if (shouldUseOpenGL && currentDemoId != showOpenGL)
  121. {
  122. if (openGLWrapperComp == nullptr)
  123. {
  124. addAndMakeVisible (openGLWrapperComp = new DemoOpenGLComp (currentDemo));
  125. openGLWrapperComp->setBounds ("0, 0, parent.width, parent.height");
  126. }
  127. }
  128. else
  129. {
  130. openGLWrapperComp = nullptr;
  131. addAndMakeVisible (currentDemo);
  132. resized();
  133. }
  134. #endif
  135. }
  136. //==============================================================================
  137. // The following methods implement the ApplicationCommandTarget interface, allowing
  138. // this window to publish a set of actions it can perform, and which can be mapped
  139. // onto menus, keypresses, etc.
  140. ApplicationCommandTarget* getNextCommandTarget()
  141. {
  142. // this will return the next parent component that is an ApplicationCommandTarget (in this
  143. // case, there probably isn't one, but it's best to use this method in your own apps).
  144. return findFirstTargetParentComponent();
  145. }
  146. void getAllCommands (Array <CommandID>& commands)
  147. {
  148. // this returns the set of all commands that this target can perform..
  149. const CommandID ids[] = { showRendering,
  150. showFontsAndText,
  151. showWidgets,
  152. showThreading,
  153. showTreeView,
  154. showTable,
  155. showAudio,
  156. showDragAndDrop,
  157. showOpenGL,
  158. showQuicktime,
  159. showDirectShow,
  160. showCamera,
  161. showWebBrowser,
  162. showCodeEditor,
  163. showInterprocessComms,
  164. setDefaultLookAndFeel,
  165. setOldSchoolLookAndFeel,
  166. useNativeTitleBar
  167. #if JUCE_MAC
  168. , useNativeMenus
  169. #endif
  170. #if ! JUCE_LINUX
  171. , goToKioskMode
  172. #endif
  173. };
  174. commands.addArray (ids, numElementsInArray (ids));
  175. }
  176. // This method is used when something needs to find out the details about one of the commands
  177. // that this object can perform..
  178. void getCommandInfo (CommandID commandID, ApplicationCommandInfo& result)
  179. {
  180. const String generalCategory ("General");
  181. const String demosCategory ("Demos");
  182. switch (commandID)
  183. {
  184. case showRendering:
  185. result.setInfo ("Graphics Rendering", "Shows the graphics demo", demosCategory, 0);
  186. result.setTicked (currentDemoId == showRendering);
  187. result.addDefaultKeypress ('1', ModifierKeys::commandModifier);
  188. break;
  189. case showFontsAndText:
  190. result.setInfo ("Fonts and Text", "Shows the fonts & text demo", demosCategory, 0);
  191. result.setTicked (currentDemoId == showFontsAndText);
  192. result.addDefaultKeypress ('2', ModifierKeys::commandModifier);
  193. break;
  194. case showWidgets:
  195. result.setInfo ("Widgets", "Shows the widgets demo", demosCategory, 0);
  196. result.setTicked (currentDemoId == showWidgets);
  197. result.addDefaultKeypress ('3', ModifierKeys::commandModifier);
  198. break;
  199. case showThreading:
  200. result.setInfo ("Multithreading", "Shows the threading demo", demosCategory, 0);
  201. result.setTicked (currentDemoId == showThreading);
  202. result.addDefaultKeypress ('4', ModifierKeys::commandModifier);
  203. break;
  204. case showTreeView:
  205. result.setInfo ("Treeviews", "Shows the treeviews demo", demosCategory, 0);
  206. result.setTicked (currentDemoId == showTreeView);
  207. result.addDefaultKeypress ('5', ModifierKeys::commandModifier);
  208. break;
  209. case showTable:
  210. result.setInfo ("Table Components", "Shows the table component demo", demosCategory, 0);
  211. result.setTicked (currentDemoId == showTable);
  212. result.addDefaultKeypress ('6', ModifierKeys::commandModifier);
  213. break;
  214. case showAudio:
  215. result.setInfo ("Audio", "Shows the audio demo", demosCategory, 0);
  216. result.setTicked (currentDemoId == showAudio);
  217. result.addDefaultKeypress ('7', ModifierKeys::commandModifier);
  218. break;
  219. case showDragAndDrop:
  220. result.setInfo ("Drag-and-drop", "Shows the drag & drop demo", demosCategory, 0);
  221. result.setTicked (currentDemoId == showDragAndDrop);
  222. result.addDefaultKeypress ('8', ModifierKeys::commandModifier);
  223. break;
  224. case showOpenGL:
  225. result.setInfo ("OpenGL", "Shows the OpenGL demo", demosCategory, 0);
  226. result.addDefaultKeypress ('9', ModifierKeys::commandModifier);
  227. result.setTicked (currentDemoId == showOpenGL);
  228. #if ! JUCE_OPENGL
  229. result.setActive (false);
  230. #endif
  231. break;
  232. case showQuicktime:
  233. result.setInfo ("Quicktime", "Shows the Quicktime demo", demosCategory, 0);
  234. result.addDefaultKeypress ('b', ModifierKeys::commandModifier);
  235. result.setTicked (currentDemoId == showQuicktime);
  236. #if ! (JUCE_QUICKTIME && ! JUCE_LINUX)
  237. result.setActive (false);
  238. #endif
  239. break;
  240. case showDirectShow:
  241. result.setInfo ("DirectShow", "Shows the DirectShow demo", demosCategory, 0);
  242. result.addDefaultKeypress ('b', ModifierKeys::commandModifier);
  243. result.setTicked (currentDemoId == showDirectShow);
  244. #if ! JUCE_DIRECTSHOW
  245. result.setActive (false);
  246. #endif
  247. break;
  248. case showCamera:
  249. result.setInfo ("Camera Capture", "Shows the camera demo", demosCategory, 0);
  250. result.addDefaultKeypress ('c', ModifierKeys::commandModifier);
  251. result.setTicked (currentDemoId == showCamera);
  252. #if ! JUCE_USE_CAMERA
  253. result.setActive (false);
  254. #endif
  255. break;
  256. case showWebBrowser:
  257. result.setInfo ("Web Browser", "Shows the web browser demo", demosCategory, 0);
  258. result.addDefaultKeypress ('i', ModifierKeys::commandModifier);
  259. result.setTicked (currentDemoId == showWebBrowser);
  260. #if (! JUCE_WEB_BROWSER) || JUCE_LINUX
  261. result.setActive (false);
  262. #endif
  263. break;
  264. case showCodeEditor:
  265. result.setInfo ("Code Editor", "Shows the code editor demo", demosCategory, 0);
  266. result.addDefaultKeypress ('e', ModifierKeys::commandModifier);
  267. result.setTicked (currentDemoId == showCodeEditor);
  268. break;
  269. case showInterprocessComms:
  270. result.setInfo ("Interprocess Comms", "Shows the interprocess communications demo", demosCategory, 0);
  271. result.addDefaultKeypress ('0', ModifierKeys::commandModifier);
  272. result.setTicked (currentDemoId == showInterprocessComms);
  273. break;
  274. case setDefaultLookAndFeel:
  275. result.setInfo ("Use default look-and-feel", String::empty, generalCategory, 0);
  276. result.setTicked (dynamic_cast <OldSchoolLookAndFeel*> (&getLookAndFeel()) == 0);
  277. break;
  278. case setOldSchoolLookAndFeel:
  279. result.setInfo ("Use the old, original juce look-and-feel", String::empty, generalCategory, 0);
  280. result.setTicked (dynamic_cast <OldSchoolLookAndFeel*> (&getLookAndFeel()) != 0);
  281. break;
  282. case useNativeTitleBar:
  283. result.setInfo ("Use native window title bar", String::empty, generalCategory, 0);
  284. result.setTicked (mainWindow.isUsingNativeTitleBar());
  285. break;
  286. #if JUCE_MAC
  287. case useNativeMenus:
  288. result.setInfo ("Use the native OSX menu bar", String::empty, generalCategory, 0);
  289. result.setTicked (MenuBarModel::getMacMainMenu() != 0);
  290. break;
  291. #endif
  292. #if ! JUCE_LINUX
  293. case goToKioskMode:
  294. result.setInfo ("Show full-screen kiosk mode", String::empty, generalCategory, 0);
  295. result.setTicked (Desktop::getInstance().getKioskModeComponent() != 0);
  296. break;
  297. #endif
  298. default:
  299. break;
  300. };
  301. }
  302. // this is the ApplicationCommandTarget method that is used to actually perform one of our commands..
  303. bool perform (const InvocationInfo& info)
  304. {
  305. switch (info.commandID)
  306. {
  307. case showRendering:
  308. showDemo (createRenderingDemo());
  309. currentDemoId = showRendering;
  310. break;
  311. case showFontsAndText:
  312. showDemo (createFontsAndTextDemo());
  313. currentDemoId = showFontsAndText;
  314. break;
  315. case showWidgets:
  316. showDemo (createWidgetsDemo());
  317. currentDemoId = showWidgets;
  318. break;
  319. case showThreading:
  320. showDemo (createThreadingDemo());
  321. currentDemoId = showThreading;
  322. break;
  323. case showTreeView:
  324. showDemo (createTreeViewDemo());
  325. currentDemoId = showTreeView;
  326. break;
  327. case showTable:
  328. showDemo (createTableDemo());
  329. currentDemoId = showTable;
  330. break;
  331. case showAudio:
  332. showDemo (createAudioDemo());
  333. currentDemoId = showAudio;
  334. break;
  335. case showDragAndDrop:
  336. showDemo (createDragAndDropDemo());
  337. currentDemoId = showDragAndDrop;
  338. break;
  339. case showOpenGL:
  340. #if JUCE_OPENGL
  341. setUsingOpenGLRenderer (false);
  342. showDemo (createOpenGLDemo());
  343. currentDemoId = showOpenGL;
  344. #endif
  345. break;
  346. case showQuicktime:
  347. #if JUCE_QUICKTIME && ! JUCE_LINUX
  348. setUsingOpenGLRenderer (false);
  349. showDemo (createQuickTimeDemo());
  350. currentDemoId = showQuicktime;
  351. #endif
  352. break;
  353. case showDirectShow:
  354. #if JUCE_DIRECTSHOW
  355. setUsingOpenGLRenderer (false);
  356. showDemo (createDirectShowDemo());
  357. currentDemoId = showDirectShow;
  358. #endif
  359. break;
  360. case showCamera:
  361. #if JUCE_USE_CAMERA
  362. setUsingOpenGLRenderer (false);
  363. showDemo (createCameraDemo());
  364. currentDemoId = showCamera;
  365. #endif
  366. break;
  367. case showWebBrowser:
  368. #if JUCE_WEB_BROWSER
  369. setUsingOpenGLRenderer (false);
  370. showDemo (createWebBrowserDemo());
  371. currentDemoId = showWebBrowser;
  372. #endif
  373. break;
  374. case showCodeEditor:
  375. showDemo (createCodeEditorDemo());
  376. currentDemoId = showCodeEditor;
  377. break;
  378. case showInterprocessComms:
  379. showDemo (createInterprocessCommsDemo());
  380. currentDemoId = showInterprocessComms;
  381. break;
  382. case setDefaultLookAndFeel:
  383. LookAndFeel::setDefaultLookAndFeel (nullptr);
  384. break;
  385. case setOldSchoolLookAndFeel:
  386. LookAndFeel::setDefaultLookAndFeel (&oldLookAndFeel);
  387. break;
  388. case useNativeTitleBar:
  389. mainWindow.setUsingNativeTitleBar (! mainWindow.isUsingNativeTitleBar());
  390. break;
  391. #if JUCE_MAC
  392. case useNativeMenus:
  393. if (MenuBarModel::getMacMainMenu() != 0)
  394. {
  395. MenuBarModel::setMacMainMenu (0);
  396. mainWindow.setMenuBar ((ContentComp*) mainWindow.getContentComponent());
  397. }
  398. else
  399. {
  400. MenuBarModel::setMacMainMenu ((ContentComp*) mainWindow.getContentComponent());
  401. mainWindow.setMenuBar (0);
  402. }
  403. break;
  404. #endif
  405. #if ! JUCE_LINUX
  406. case goToKioskMode:
  407. {
  408. Desktop& desktop = Desktop::getInstance();
  409. if (desktop.getKioskModeComponent() == nullptr)
  410. desktop.setKioskModeComponent (getTopLevelComponent());
  411. else
  412. desktop.setKioskModeComponent (nullptr);
  413. break;
  414. }
  415. #endif
  416. default:
  417. return false;
  418. };
  419. return true;
  420. }
  421. private:
  422. //==============================================================================
  423. MainDemoWindow& mainWindow;
  424. OldSchoolLookAndFeel oldLookAndFeel;
  425. ScopedPointer<Component> currentDemo;
  426. int currentDemoId;
  427. TooltipWindow tooltipWindow; // to add tooltips to an application, you
  428. // just need to create one of these and leave it
  429. // there to do its work..
  430. //==============================================================================
  431. #if JUCE_OPENGL
  432. class DemoOpenGLComp : public OpenGLComponent
  433. {
  434. public:
  435. DemoOpenGLComp (Component* contentComp)
  436. : OpenGLComponent (useBackgroundThread | allowSubComponents)
  437. {
  438. addAndMakeVisible (contentComp);
  439. }
  440. ~DemoOpenGLComp()
  441. {
  442. // It's essential to call this method before our class is destroyed, to
  443. // make sure that the background renderer thread doesn't try to call it
  444. // while it's being dismantled..
  445. stopRenderThread();
  446. }
  447. void newOpenGLContextCreated() {}
  448. void renderOpenGL() {}
  449. void paint (Graphics& g)
  450. {
  451. g.fillAll (Colours::azure);
  452. }
  453. };
  454. ScopedPointer<DemoOpenGLComp> openGLWrapperComp;
  455. #endif
  456. StringArray getRenderingEngines()
  457. {
  458. StringArray renderingEngines (getPeer()->getAvailableRenderingEngines());
  459. #if JUCE_OPENGL
  460. renderingEngines.add ("Use OpenGL Renderer");
  461. #endif
  462. return renderingEngines;
  463. }
  464. //==============================================================================
  465. enum CommandIDs
  466. {
  467. showRendering = 0x2000,
  468. showFontsAndText = 0x2001,
  469. showWidgets = 0x2002,
  470. showThreading = 0x2003,
  471. showTreeView = 0x2004,
  472. showAudio = 0x2005,
  473. showDragAndDrop = 0x2006,
  474. showOpenGL = 0x2007,
  475. showQuicktime = 0x2008,
  476. showInterprocessComms = 0x2009,
  477. showTable = 0x2010,
  478. showCamera = 0x2011,
  479. showWebBrowser = 0x2012,
  480. showCodeEditor = 0x2013,
  481. showDirectShow = 0x2014,
  482. setDefaultLookAndFeel = 0x200b,
  483. setOldSchoolLookAndFeel = 0x200c,
  484. useNativeTitleBar = 0x200d,
  485. useNativeMenus = 0x200e,
  486. goToKioskMode = 0x200f
  487. };
  488. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ContentComp);
  489. };
  490. //==============================================================================
  491. #if JUCE_WINDOWS || JUCE_LINUX
  492. // Just add a simple icon to the Window system tray area..
  493. class DemoTaskbarComponent : public SystemTrayIconComponent
  494. {
  495. public:
  496. DemoTaskbarComponent()
  497. {
  498. // Create an icon which is just a square with a "j" in it..
  499. Image icon (Image::RGB, 32, 32, true);
  500. Graphics g (icon);
  501. g.fillAll (Colours::lightblue);
  502. g.setColour (Colours::black);
  503. g.setFont ((float) icon.getHeight(), Font::bold);
  504. g.drawText ("j", 0, 0, icon.getWidth(), icon.getHeight(), Justification::centred, false);
  505. setIconImage (icon);
  506. setIconTooltip ("Juce Demo App!");
  507. }
  508. void mouseDown (const MouseEvent&)
  509. {
  510. PopupMenu m;
  511. m.addItem (1, "Quit the Juce demo");
  512. const int result = m.show();
  513. if (result == 1)
  514. JUCEApplication::getInstance()->systemRequestedQuit();
  515. }
  516. };
  517. #endif
  518. //==============================================================================
  519. MainDemoWindow::MainDemoWindow()
  520. : DocumentWindow ("JUCE Demo!",
  521. Colours::azure,
  522. DocumentWindow::allButtons,
  523. true)
  524. {
  525. setResizable (true, false); // resizability is a property of ResizableWindow
  526. setResizeLimits (400, 300, 8192, 8192);
  527. ContentComp* contentComp = new ContentComp (*this);
  528. commandManager.registerAllCommandsForTarget (contentComp);
  529. commandManager.registerAllCommandsForTarget (JUCEApplication::getInstance());
  530. // this lets the command manager use keypresses that arrive in our window to send
  531. // out commands
  532. addKeyListener (commandManager.getKeyMappings());
  533. // sets the main content component for the window to be this tabbed
  534. // panel. This will be deleted when the window is deleted.
  535. setContentOwned (contentComp, false);
  536. // this tells the DocumentWindow to automatically create and manage a MenuBarComponent
  537. // which uses our contentComp as its MenuBarModel
  538. setMenuBar (contentComp);
  539. // tells our menu bar model that it should watch this command manager for
  540. // changes, and send change messages accordingly.
  541. contentComp->setApplicationCommandManagerToWatch (&commandManager);
  542. setVisible (true);
  543. #if JUCE_WINDOWS || JUCE_LINUX
  544. taskbarIcon = new DemoTaskbarComponent();
  545. #endif
  546. }
  547. MainDemoWindow::~MainDemoWindow()
  548. {
  549. // because we've set the content comp to be used as our menu bar model, we
  550. // have to switch this off before deleting the content comp..
  551. setMenuBar (nullptr);
  552. #if JUCE_MAC // ..and also the main bar if we're using that on a Mac...
  553. MenuBarModel::setMacMainMenu (nullptr);
  554. #endif
  555. // clearing the content component will delete the current one, and
  556. // that will in turn delete all its child components. You don't always
  557. // have to do this explicitly, because the base class's destructor will
  558. // also delete the content component, but in this case we need to
  559. // make sure our content comp has gone away before deleting our command
  560. // manager.
  561. clearContentComponent();
  562. }
  563. void MainDemoWindow::closeButtonPressed()
  564. {
  565. // The correct thing to do when you want the app to quit is to call the
  566. // JUCEApplication::systemRequestedQuit() method.
  567. // That means that requests to quit that come from your own UI, or from other
  568. // OS-specific sources (e.g. the dock menu on the mac) all get handled in the
  569. // same way.
  570. JUCEApplication::getInstance()->systemRequestedQuit();
  571. }