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.

357 lines
11KB

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