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.

666 lines
24KB

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