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.

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