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.

615 lines
22KB

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