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.

354 lines
11KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2015 - ROLI Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. #include "../JuceDemoHeader.h"
  18. //==============================================================================
  19. /** Just a simple window that deletes itself when closed. */
  20. class BasicWindow : public DocumentWindow
  21. {
  22. public:
  23. BasicWindow (const String& name, Colour backgroundColour, int buttonsNeeded)
  24. : DocumentWindow (name, backgroundColour, buttonsNeeded)
  25. {
  26. }
  27. void closeButtonPressed()
  28. {
  29. delete this;
  30. }
  31. private:
  32. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BasicWindow)
  33. };
  34. //==============================================================================
  35. /** This window contains a ColourSelector which can be used to change the window's colour. */
  36. class ColourSelectorWindow : public DocumentWindow,
  37. private ChangeListener
  38. {
  39. public:
  40. ColourSelectorWindow (const String& name, Colour backgroundColour, int buttonsNeeded)
  41. : DocumentWindow (name, backgroundColour, buttonsNeeded),
  42. selector (ColourSelector::showColourAtTop
  43. | ColourSelector::showSliders
  44. | ColourSelector::showColourspace)
  45. {
  46. selector.setCurrentColour (backgroundColour);
  47. selector.setColour (ColourSelector::backgroundColourId, Colours::transparentWhite);
  48. selector.addChangeListener (this);
  49. setContentOwned (&selector, false);
  50. }
  51. ~ColourSelectorWindow()
  52. {
  53. selector.removeChangeListener (this);
  54. }
  55. void closeButtonPressed()
  56. {
  57. delete this;
  58. }
  59. private:
  60. ColourSelector selector;
  61. void changeListenerCallback (ChangeBroadcaster* source)
  62. {
  63. if (source == &selector)
  64. setBackgroundColour (selector.getCurrentColour());
  65. }
  66. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ColourSelectorWindow)
  67. };
  68. //==============================================================================
  69. class BouncingBallComponent : public Component,
  70. public Timer
  71. {
  72. public:
  73. BouncingBallComponent()
  74. {
  75. setInterceptsMouseClicks (false, false);
  76. Random random;
  77. const float size = 10.0f + random.nextInt (30);
  78. ballBounds.setBounds (random.nextFloat() * 100.0f,
  79. random.nextFloat() * 100.0f,
  80. size, size);
  81. direction.x = random.nextFloat() * 8.0f - 4.0f;
  82. direction.y = random.nextFloat() * 8.0f - 4.0f;
  83. colour = Colour ((juce::uint32) random.nextInt())
  84. .withAlpha (0.5f)
  85. .withBrightness (0.7f);
  86. startTimer (60);
  87. }
  88. void paint (Graphics& g) override
  89. {
  90. g.setColour (colour);
  91. g.fillEllipse (ballBounds - getPosition().toFloat());
  92. }
  93. void timerCallback() override
  94. {
  95. ballBounds += direction;
  96. if (ballBounds.getX() < 0) direction.x = std::abs (direction.x);
  97. if (ballBounds.getY() < 0) direction.y = std::abs (direction.y);
  98. if (ballBounds.getRight() > getParentWidth()) direction.x = -std::abs (direction.x);
  99. if (ballBounds.getBottom() > getParentHeight()) direction.y = -std::abs (direction.y);
  100. setBounds (ballBounds.getSmallestIntegerContainer());
  101. }
  102. private:
  103. Colour colour;
  104. Rectangle<float> ballBounds;
  105. Point<float> direction;
  106. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BouncingBallComponent)
  107. };
  108. //==============================================================================
  109. class BouncingBallsContainer : public Component
  110. {
  111. public:
  112. BouncingBallsContainer (int numBalls)
  113. {
  114. for (int i = 0; i < numBalls; ++i)
  115. {
  116. BouncingBallComponent* newBall = new BouncingBallComponent();
  117. balls.add (newBall);
  118. addAndMakeVisible (newBall);
  119. }
  120. }
  121. void mouseDown (const MouseEvent& e) override
  122. {
  123. dragger.startDraggingComponent (this, e);
  124. }
  125. void mouseDrag (const MouseEvent& e) override
  126. {
  127. // as there's no titlebar we have to manage the dragging ourselves
  128. dragger.dragComponent (this, e, 0);
  129. }
  130. void paint (Graphics& g) override
  131. {
  132. if (isOpaque())
  133. g.fillAll (Colours::white);
  134. else
  135. g.fillAll (Colours::blue.withAlpha (0.2f));
  136. g.setFont (16.0f);
  137. g.setColour (Colours::black);
  138. g.drawFittedText ("This window has no titlebar and a transparent background.",
  139. getLocalBounds().reduced (8, 0),
  140. Justification::centred, 5);
  141. g.drawRect (getLocalBounds());
  142. }
  143. private:
  144. ComponentDragger dragger;
  145. OwnedArray<BouncingBallComponent> balls;
  146. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BouncingBallsContainer)
  147. };
  148. //==============================================================================
  149. class WindowsDemo : public Component,
  150. private Button::Listener
  151. {
  152. public:
  153. enum Windows
  154. {
  155. dialog,
  156. document,
  157. alert,
  158. numWindows
  159. };
  160. WindowsDemo()
  161. {
  162. setOpaque (true);
  163. showWindowsButton.setButtonText ("Show Windows");
  164. addAndMakeVisible (showWindowsButton);
  165. showWindowsButton.addListener (this);
  166. closeWindowsButton.setButtonText ("Close Windows");
  167. addAndMakeVisible (closeWindowsButton);
  168. closeWindowsButton.addListener (this);
  169. }
  170. ~WindowsDemo()
  171. {
  172. if (dialogWindow != nullptr)
  173. {
  174. dialogWindow->exitModalState (0);
  175. // we are shutting down: can't wait for the message manager
  176. // to eventually delete this
  177. delete dialogWindow;
  178. }
  179. closeAllWindows();
  180. closeWindowsButton.removeListener (this);
  181. showWindowsButton.removeListener (this);
  182. }
  183. void paint (Graphics& g) override
  184. {
  185. g.fillAll (Colours::grey);
  186. }
  187. void resized() override
  188. {
  189. const Rectangle<int> buttonSize (0, 0, 108, 28);
  190. Rectangle<int> area ((getWidth() / 2) - (buttonSize.getWidth() / 2),
  191. (getHeight() / 2) - buttonSize.getHeight(),
  192. buttonSize.getWidth(), buttonSize.getHeight());
  193. showWindowsButton.setBounds (area.reduced (2));
  194. closeWindowsButton.setBounds (area.translated (0, buttonSize.getHeight()).reduced (2));
  195. }
  196. private:
  197. // Because in this demo the windows delete themselves, we'll use the
  198. // Component::SafePointer class to point to them, which automatically becomes
  199. // null when the component that it points to is deleted.
  200. Array< Component::SafePointer<Component> > windows;
  201. TextButton showWindowsButton, closeWindowsButton;
  202. SafePointer<DialogWindow> dialogWindow;
  203. void showAllWindows()
  204. {
  205. closeAllWindows();
  206. showDocumentWindow (false);
  207. showDocumentWindow (true);
  208. showTransparentWindow();
  209. showDialogWindow();
  210. }
  211. void closeAllWindows()
  212. {
  213. for (int i = 0; i < windows.size(); ++i)
  214. windows.getReference(i).deleteAndZero();
  215. windows.clear();
  216. }
  217. void showDialogWindow()
  218. {
  219. String m;
  220. m << "Dialog Windows can be used to quickly show a component, usually blocking mouse input to other windows." << newLine
  221. << newLine
  222. << "They can also be quickly closed with the escape key, try it now.";
  223. DialogWindow::LaunchOptions options;
  224. Label* label = new Label();
  225. label->setText (m, dontSendNotification);
  226. label->setColour (Label::textColourId, Colours::whitesmoke);
  227. options.content.setOwned (label);
  228. Rectangle<int> area (0, 0, 300, 200);
  229. options.content->setSize (area.getWidth(), area.getHeight());
  230. options.dialogTitle = "Dialog Window";
  231. options.dialogBackgroundColour = Colour (0xff0e345a);
  232. options.escapeKeyTriggersCloseButton = true;
  233. options.useNativeTitleBar = false;
  234. options.resizable = true;
  235. dialogWindow = options.launchAsync();
  236. if (dialogWindow != nullptr)
  237. dialogWindow->centreWithSize (300, 200);
  238. }
  239. void showDocumentWindow (bool native)
  240. {
  241. DocumentWindow* dw = new ColourSelectorWindow ("Document Window", getRandomBrightColour(), DocumentWindow::allButtons);
  242. windows.add (dw);
  243. Rectangle<int> area (0, 0, 300, 400);
  244. RectanglePlacement placement ((native ? RectanglePlacement::xLeft
  245. : RectanglePlacement::xRight)
  246. | RectanglePlacement::yTop
  247. | RectanglePlacement::doNotResize);
  248. Rectangle<int> result (placement.appliedTo (area, Desktop::getInstance().getDisplays()
  249. .getMainDisplay().userArea.reduced (20)));
  250. dw->setBounds (result);
  251. dw->setResizable (true, ! native);
  252. dw->setUsingNativeTitleBar (native);
  253. dw->setVisible (true);
  254. }
  255. void showTransparentWindow()
  256. {
  257. BouncingBallsContainer* balls = new BouncingBallsContainer (3);
  258. balls->addToDesktop (ComponentPeer::windowIsTemporary);
  259. windows.add (balls);
  260. Rectangle<int> area (0, 0, 200, 200);
  261. RectanglePlacement placement (RectanglePlacement::xLeft
  262. | RectanglePlacement::yBottom
  263. | RectanglePlacement::doNotResize);
  264. Rectangle<int> result (placement.appliedTo (area, Desktop::getInstance().getDisplays()
  265. .getMainDisplay().userArea.reduced (20)));
  266. balls->setBounds (result);
  267. balls->setVisible (true);
  268. }
  269. void buttonClicked (Button* button) override
  270. {
  271. if (button == &showWindowsButton)
  272. showAllWindows();
  273. else if (button == &closeWindowsButton)
  274. closeAllWindows();
  275. }
  276. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WindowsDemo)
  277. };
  278. // This static object will register this demo type in a global list of demos..
  279. static JuceDemoType<WindowsDemo> demo ("10 Components: Windows");