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.

716 lines
25KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-12 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 "../JuceDemoHeader.h"
  19. /** Holds the various toggle buttons for the animation modes. */
  20. class ControllersComponent : public Component
  21. {
  22. public:
  23. ControllersComponent()
  24. {
  25. setOpaque (true);
  26. initialiseToggle (animatePosition, "Animate Position", true);
  27. initialiseToggle (animateRotation, "Animate Rotation", true);
  28. initialiseToggle (animateSize, "Animate Size", false);
  29. initialiseToggle (animateShear, "Animate Shearing", false);
  30. initialiseToggle (animateAlpha, "Animate Alpha", false);
  31. initialiseToggle (clipToRectangle, "Clip to Rectangle", false);
  32. initialiseToggle (clipToPath, "Clip to Path", false);
  33. initialiseToggle (clipToImage, "Clip to Image", false);
  34. initialiseToggle (quality, "Higher quality image interpolation", false);
  35. }
  36. void paint (Graphics& g)
  37. {
  38. fillTiledBackground (g);
  39. }
  40. void resized() override
  41. {
  42. Rectangle<int> r (getLocalBounds().reduced (4));
  43. int buttonHeight = 22;
  44. Rectangle<int> columns (r.removeFromTop (buttonHeight * 4));
  45. Rectangle<int> col (columns.removeFromLeft (200));
  46. animatePosition.setBounds (col.removeFromTop (buttonHeight));
  47. animateRotation.setBounds (col.removeFromTop (buttonHeight));
  48. animateSize.setBounds (col.removeFromTop (buttonHeight));
  49. animateShear.setBounds (col.removeFromTop (buttonHeight));
  50. columns.removeFromLeft (20);
  51. col = columns.removeFromLeft (200);
  52. animateAlpha.setBounds (col.removeFromTop (buttonHeight));
  53. clipToRectangle.setBounds (col.removeFromTop (buttonHeight));
  54. clipToPath.setBounds (col.removeFromTop (buttonHeight));
  55. clipToImage.setBounds (col.removeFromTop (buttonHeight));
  56. r.removeFromBottom (6);
  57. quality.setBounds (r.removeFromTop (buttonHeight));
  58. }
  59. void initialiseToggle (ToggleButton& b, const char* name, bool on)
  60. {
  61. addAndMakeVisible (b);
  62. b.setButtonText (name);
  63. b.setToggleState (on, dontSendNotification);
  64. }
  65. ToggleButton animateRotation, animatePosition, animateAlpha, animateSize, animateShear;
  66. ToggleButton clipToRectangle, clipToPath, clipToImage, quality;
  67. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ControllersComponent)
  68. };
  69. //==============================================================================
  70. class GraphicsDemoBase : public Component
  71. {
  72. public:
  73. GraphicsDemoBase (ControllersComponent& cc, const String& name)
  74. : Component (name), controls (cc),
  75. lastRenderStartTime (0),
  76. averageTimeMs (0),
  77. averageActualFPS (0)
  78. {
  79. displayFont = Font (Font::getDefaultMonospacedFontName(), 12.0f, Font::bold);
  80. }
  81. AffineTransform getTransform()
  82. {
  83. const float hw = 0.5f * getWidth();
  84. const float hh = 0.5f * getHeight();
  85. AffineTransform t;
  86. if (controls.animateRotation.getToggleState())
  87. t = t.rotated (rotation.getValue() * float_Pi * 2.0f);
  88. if (controls.animateSize.getToggleState())
  89. t = t.scaled (0.3f + size.getValue() * 2.0f);
  90. if (controls.animatePosition.getToggleState())
  91. t = t.translated (hw + hw * (offsetX.getValue() - 0.5f),
  92. hh + hh * (offsetY.getValue() - 0.5f));
  93. else
  94. t = t.translated (hw, hh);
  95. if (controls.animateShear.getToggleState())
  96. t = t.sheared (shear.getValue() * 2.0f - 1.0f, 0.0f);
  97. return t;
  98. }
  99. float getAlpha() const
  100. {
  101. if (controls.animateAlpha.getToggleState())
  102. return alpha.getValue();
  103. return 1.0f;
  104. }
  105. void paint (Graphics& g) override
  106. {
  107. double startTime = 0.0;
  108. {
  109. // A ScopedSaveState will return the Graphics context to the state it was at the time of
  110. // construction when it goes out of scope. We use it here to avoid clipping the fps text
  111. const Graphics::ScopedSaveState state (g);
  112. if (controls.clipToRectangle.getToggleState()) clipToRectangle (g);
  113. if (controls.clipToPath .getToggleState()) clipToPath (g);
  114. if (controls.clipToImage .getToggleState()) clipToImage (g);
  115. g.setImageResamplingQuality (controls.quality.getToggleState() ? Graphics::highResamplingQuality
  116. : Graphics::mediumResamplingQuality);
  117. // take a note of the time before the render
  118. startTime = Time::getMillisecondCounterHiRes();
  119. // then let the demo draw itself..
  120. drawDemo (g);
  121. }
  122. double now = Time::getMillisecondCounterHiRes();
  123. double filtering = 0.08;
  124. const double elapsedMs = now - startTime;
  125. averageTimeMs += (elapsedMs - averageTimeMs) * filtering;
  126. const double sinceLastRender = now - lastRenderStartTime;
  127. lastRenderStartTime = now;
  128. const double effectiveFPS = 1000.0 / averageTimeMs;
  129. const double actualFPS = sinceLastRender > 0 ? (1000.0 / sinceLastRender) : 0;
  130. averageActualFPS += (actualFPS - averageActualFPS) * filtering;
  131. GlyphArrangement ga;
  132. ga.addFittedText (displayFont,
  133. "Time: " + String (averageTimeMs, 2)
  134. + " ms\nEffective FPS: " + String (effectiveFPS, 1)
  135. + "\nActual FPS: " + String (averageActualFPS, 1),
  136. 0, 10.0f, getWidth() - 10.0f, (float) getHeight(), Justification::topRight, 3);
  137. g.setColour (Colours::white.withAlpha (0.5f));
  138. g.fillRect (ga.getBoundingBox (0, ga.getNumGlyphs(), true).getSmallestIntegerContainer().expanded (4));
  139. g.setColour (Colours::black);
  140. ga.draw (g);
  141. }
  142. virtual void drawDemo (Graphics&) = 0;
  143. void clipToRectangle (Graphics& g)
  144. {
  145. int w = getWidth() / 2;
  146. int h = getHeight() / 2;
  147. int x = (int) (w * clipRectX.getValue());
  148. int y = (int) (h * clipRectY.getValue());
  149. g.reduceClipRegion (x, y, w, h);
  150. }
  151. void clipToPath (Graphics& g)
  152. {
  153. float pathSize = (float) jmin (getWidth(), getHeight());
  154. Path p;
  155. p.addStar (Point<float> (clipPathX.getValue(),
  156. clipPathY.getValue()) * pathSize,
  157. 7,
  158. pathSize * (0.5f + clipPathDepth.getValue()),
  159. pathSize * 0.5f,
  160. clipPathAngle.getValue());
  161. g.reduceClipRegion (p, AffineTransform::identity);
  162. }
  163. void clipToImage (Graphics& g)
  164. {
  165. if (! clipImage.isValid())
  166. createClipImage();
  167. AffineTransform transform (AffineTransform::translation (clipImage.getWidth() / -2.0f,
  168. clipImage.getHeight() / -2.0f)
  169. .rotated (clipImageAngle.getValue() * float_Pi * 2.0f)
  170. .scaled (2.0f + clipImageSize.getValue() * 3.0f)
  171. .translated (getWidth() * 0.5f,
  172. getHeight() * 0.5f));
  173. g.reduceClipRegion (clipImage, transform);
  174. }
  175. void createClipImage()
  176. {
  177. clipImage = Image (Image::ARGB, 300, 300, true);
  178. Graphics g (clipImage);
  179. g.setGradientFill (ColourGradient (Colours::transparentBlack, 0, 0,
  180. Colours::black, 0, 300, false));
  181. for (int i = 0; i < 20; ++i)
  182. g.fillRect (Random::getSystemRandom().nextInt (200),
  183. Random::getSystemRandom().nextInt (200),
  184. Random::getSystemRandom().nextInt (100),
  185. Random::getSystemRandom().nextInt (100));
  186. }
  187. //==============================================================================
  188. ControllersComponent& controls;
  189. SlowerBouncingNumber offsetX, offsetY, rotation, size, shear, alpha, clipRectX,
  190. clipRectY, clipPathX, clipPathY, clipPathDepth, clipPathAngle,
  191. clipImageX, clipImageY, clipImageAngle, clipImageSize;
  192. double lastRenderStartTime, averageTimeMs, averageActualFPS;
  193. Image clipImage;
  194. Font displayFont;
  195. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GraphicsDemoBase)
  196. };
  197. //==============================================================================
  198. class RectangleFillTypesDemo : public GraphicsDemoBase
  199. {
  200. public:
  201. RectangleFillTypesDemo (ControllersComponent& cc)
  202. : GraphicsDemoBase (cc, "Fill Types: Rectangles"),
  203. colour1 (Colours::red),
  204. colour2 (Colours::green)
  205. {
  206. }
  207. void drawDemo (Graphics& g) override
  208. {
  209. g.addTransform (getTransform());
  210. const int rectSize = jmin (getWidth(), getHeight()) / 2 - 20;
  211. g.setColour (colour1.withAlpha (getAlpha()));
  212. g.fillRect (-rectSize, -rectSize, rectSize, rectSize);
  213. g.setGradientFill (ColourGradient (colour1, 10.0f, (float) -rectSize,
  214. colour2, 10.0f + rectSize, 0.0f, false));
  215. g.setOpacity (getAlpha());
  216. g.fillRect (10, -rectSize, rectSize, rectSize);
  217. g.setGradientFill (ColourGradient (colour1, rectSize * -0.5f, 10.0f + rectSize * 0.5f,
  218. colour2, 0, 10.0f + rectSize, true));
  219. g.setOpacity (getAlpha());
  220. g.fillRect (-rectSize, 10, rectSize, rectSize);
  221. g.setGradientFill (ColourGradient (colour1, 10.0f, 10.0f,
  222. colour2, 10.0f + rectSize, 10.0f + rectSize, false));
  223. g.setOpacity (getAlpha());
  224. g.drawRect (10, 10, rectSize, rectSize, 5);
  225. }
  226. Colour colour1, colour2;
  227. };
  228. //==============================================================================
  229. class PathsDemo : public GraphicsDemoBase
  230. {
  231. public:
  232. PathsDemo (ControllersComponent& cc, bool linear, bool radial)
  233. : GraphicsDemoBase (cc, String ("Paths") + (radial ? ": Radial Gradients"
  234. : (linear ? ": Linear Gradients"
  235. : ": Solid"))),
  236. useLinearGradient (linear), useRadialGradient (radial)
  237. {
  238. logoPath = MainAppWindow::getJUCELogoPath();
  239. // rescale the logo path so that it's centred about the origin and has the right size.
  240. logoPath.applyTransform (RectanglePlacement (RectanglePlacement::centred)
  241. .getTransformToFit (logoPath.getBounds(),
  242. Rectangle<float> (-200.0f, -200.0f, 400.0f, 400.0f)));
  243. // Surround it with some other shapes..
  244. logoPath.addStar (Point<float> (-300.0f, -50.0f), 7, 30.0f, 70.0f, 0.1f);
  245. logoPath.addStar (Point<float> (300.0f, 50.0f), 6, 40.0f, 70.0f, 0.1f);
  246. logoPath.addEllipse (-100.0f, 150.0f, 200.0f, 140.0f);
  247. logoPath.addRectangle (-100.0f, -280.0f, 200.0f, 140.0f);
  248. }
  249. void drawDemo (Graphics& g) override
  250. {
  251. const Path& p = logoPath;
  252. if (useLinearGradient || useRadialGradient)
  253. {
  254. Colour c1 (gradientColours[0].getValue(), gradientColours[1].getValue(), gradientColours[2].getValue(), 1.0f);
  255. Colour c2 (gradientColours[3].getValue(), gradientColours[4].getValue(), gradientColours[5].getValue(), 1.0f);
  256. Colour c3 (gradientColours[6].getValue(), gradientColours[7].getValue(), gradientColours[8].getValue(), 1.0f);
  257. float x1 = gradientPositions[0].getValue() * getWidth() * 0.25f;
  258. float y1 = gradientPositions[1].getValue() * getHeight() * 0.25f;
  259. float x2 = gradientPositions[2].getValue() * getWidth() * 0.75f;
  260. float y2 = gradientPositions[3].getValue() * getHeight() * 0.75f;
  261. ColourGradient gradient (c1, x1, y1,
  262. c2, x2, y2,
  263. useRadialGradient);
  264. gradient.addColour (gradientIntermediate.getValue(), c3);
  265. g.setGradientFill (gradient);
  266. }
  267. else
  268. {
  269. g.setColour (Colours::blue);
  270. }
  271. g.setOpacity (getAlpha());
  272. g.fillPath (p, getTransform());
  273. }
  274. Path logoPath;
  275. bool useLinearGradient, useRadialGradient;
  276. SlowerBouncingNumber gradientColours[9], gradientPositions[4], gradientIntermediate;
  277. };
  278. //==============================================================================
  279. class StrokesDemo : public GraphicsDemoBase
  280. {
  281. public:
  282. StrokesDemo (ControllersComponent& cc)
  283. : GraphicsDemoBase (cc, "Paths: Stroked")
  284. {
  285. }
  286. void drawDemo (Graphics& g) override
  287. {
  288. float w = (float) getWidth();
  289. float h = (float) getHeight();
  290. Path p;
  291. p.startNewSubPath (points[0].getValue() * w,
  292. points[1].getValue() * h);
  293. for (int i = 2; i < numElementsInArray (points); i += 4)
  294. p.quadraticTo (points[i].getValue() * w,
  295. points[i + 1].getValue() * h,
  296. points[i + 2].getValue() * w,
  297. points[i + 3].getValue() * h);
  298. p.closeSubPath();
  299. PathStrokeType stroke (0.5f + 10.0f * thickness.getValue());
  300. g.setColour (Colours::purple.withAlpha (getAlpha()));
  301. g.strokePath (p, stroke, AffineTransform::identity);
  302. }
  303. SlowerBouncingNumber points[2 + 4 * 8], thickness;
  304. };
  305. //==============================================================================
  306. class ImagesRenderingDemo : public GraphicsDemoBase
  307. {
  308. public:
  309. ImagesRenderingDemo (ControllersComponent& cc, bool argb_, bool tiled_)
  310. : GraphicsDemoBase (cc, String ("Images") + (argb_ ? ": ARGB" : ": RGB") + (tiled_ ? " Tiled" : String::empty )),
  311. isArgb (argb_), isTiled (tiled_)
  312. {
  313. argbImage = ImageFileFormat::loadFrom (BinaryData::juce_icon_png, (size_t) BinaryData::juce_icon_pngSize);
  314. rgbImage = ImageFileFormat::loadFrom (BinaryData::portmeirion_jpg, (size_t) BinaryData::portmeirion_jpgSize);
  315. }
  316. void drawDemo (Graphics& g) override
  317. {
  318. Image image = isArgb ? argbImage : rgbImage;
  319. AffineTransform transform (AffineTransform::translation ((float) (image.getWidth() / -2),
  320. (float) (image.getHeight() / -2))
  321. .followedBy (getTransform()));
  322. if (isTiled)
  323. {
  324. FillType fill (image, transform);
  325. fill.setOpacity (getAlpha());
  326. g.setFillType (fill);
  327. g.fillAll();
  328. }
  329. else
  330. {
  331. g.setOpacity (getAlpha());
  332. g.drawImageTransformed (image, transform, false);
  333. }
  334. }
  335. bool isArgb, isTiled;
  336. Image rgbImage, argbImage;
  337. };
  338. //==============================================================================
  339. class GlyphsDemo : public GraphicsDemoBase
  340. {
  341. public:
  342. GlyphsDemo (ControllersComponent& cc)
  343. : GraphicsDemoBase (cc, "Glyphs")
  344. {
  345. glyphs.addFittedText (Font (20.0f), "The Quick Brown Fox Jumped Over The Lazy Dog",
  346. -120, -50, 240, 100, Justification::centred, 2, 1.0f);
  347. }
  348. void drawDemo (Graphics& g) override
  349. {
  350. g.setColour (Colours::black.withAlpha (getAlpha()));
  351. glyphs.draw (g, getTransform());
  352. }
  353. GlyphArrangement glyphs;
  354. };
  355. //==============================================================================
  356. class SVGDemo : public GraphicsDemoBase
  357. {
  358. public:
  359. SVGDemo (ControllersComponent& cc)
  360. : GraphicsDemoBase (cc, "SVG")
  361. {
  362. createSVGDrawable();
  363. }
  364. void drawDemo (Graphics& g) override
  365. {
  366. if (Time::getCurrentTime().toMilliseconds() > lastSVGLoadTime.toMilliseconds() + 2000)
  367. createSVGDrawable();
  368. svgDrawable->draw (g, getAlpha(), getTransform());
  369. }
  370. void createSVGDrawable()
  371. {
  372. lastSVGLoadTime = Time::getCurrentTime();
  373. MemoryInputStream iconsFileStream (BinaryData::icons_zip, BinaryData::icons_zipSize, false);
  374. ZipFile icons (&iconsFileStream, false);
  375. // Load a random SVG file from our embedded icons.zip file.
  376. const ScopedPointer<InputStream> svgFileStream (icons.createStreamForEntry (Random::getSystemRandom().nextInt (icons.getNumEntries())));
  377. if (svgFileStream != nullptr)
  378. {
  379. svgDrawable = dynamic_cast <DrawableComposite*> (Drawable::createFromImageDataStream (*svgFileStream));
  380. if (svgDrawable != nullptr)
  381. {
  382. // to make our icon the right size, we'll set its bounding box to the size and position that we want.
  383. svgDrawable->setBoundingBox (RelativeParallelogram (Point<float> (-100, -100),
  384. Point<float> (100, -100),
  385. Point<float> (-100, 100)));
  386. }
  387. }
  388. }
  389. Time lastSVGLoadTime;
  390. ScopedPointer<DrawableComposite> svgDrawable;
  391. };
  392. //==============================================================================
  393. class LinesDemo : public GraphicsDemoBase
  394. {
  395. public:
  396. LinesDemo (ControllersComponent& cc)
  397. : GraphicsDemoBase (cc, "Lines")
  398. {
  399. }
  400. void drawDemo (Graphics& g) override
  401. {
  402. {
  403. RectangleList<float> verticalLines;
  404. verticalLines.ensureStorageAllocated (getWidth());
  405. float pos = offset.getValue();
  406. for (int x = 0; x < getWidth(); ++x)
  407. {
  408. float y = getHeight() * 0.3f;
  409. float length = y * std::abs (std::sin (x / 100.0f + 2.0f * pos));
  410. verticalLines.addWithoutMerging (Rectangle<float> ((float) x, y - length * 0.5f, 1.0f, length));
  411. }
  412. g.setColour (Colours::blue.withAlpha (getAlpha()));
  413. g.fillRectList (verticalLines);
  414. }
  415. {
  416. RectangleList<float> horizontalLines;
  417. horizontalLines.ensureStorageAllocated (getHeight());
  418. float pos = offset.getValue();
  419. for (int y = 0; y < getHeight(); ++y)
  420. {
  421. float x = getWidth() * 0.3f;
  422. float length = x * std::abs (std::sin (y / 100.0f + 2.0f * pos));
  423. horizontalLines.addWithoutMerging (Rectangle<float> (x - length * 0.5f, (float) y, length, 1.0f));
  424. }
  425. g.setColour (Colours::green.withAlpha (getAlpha()));
  426. g.fillRectList (horizontalLines);
  427. }
  428. g.setColour (Colours::red.withAlpha (getAlpha()));
  429. const float w = (float) getWidth();
  430. const float h = (float) getHeight();
  431. g.drawLine (positions[0].getValue() * w,
  432. positions[1].getValue() * h,
  433. positions[2].getValue() * w,
  434. positions[3].getValue() * h);
  435. g.drawLine (positions[4].getValue() * w,
  436. positions[5].getValue() * h,
  437. positions[6].getValue() * w,
  438. positions[7].getValue() * h);
  439. }
  440. SlowerBouncingNumber offset, positions[8];
  441. };
  442. //==============================================================================
  443. class DemoHolderComponent : public Component,
  444. private Timer
  445. {
  446. public:
  447. DemoHolderComponent()
  448. : currentDemo (nullptr)
  449. {
  450. setOpaque (true);
  451. }
  452. void paint (Graphics& g)
  453. {
  454. g.fillCheckerBoard (getLocalBounds(), 48, 48,
  455. Colours::lightgrey, Colours::white);
  456. }
  457. void timerCallback()
  458. {
  459. if (currentDemo != nullptr)
  460. currentDemo->repaint();
  461. }
  462. void setDemo (GraphicsDemoBase* newDemo)
  463. {
  464. if (currentDemo != nullptr)
  465. removeChildComponent (currentDemo);
  466. currentDemo = newDemo;
  467. if (currentDemo != nullptr)
  468. {
  469. addAndMakeVisible (currentDemo);
  470. startTimerHz (60);
  471. resized();
  472. }
  473. }
  474. void resized()
  475. {
  476. if (currentDemo != nullptr)
  477. currentDemo->setBounds (getLocalBounds());
  478. }
  479. private:
  480. GraphicsDemoBase* currentDemo;
  481. };
  482. //==============================================================================
  483. class TestListComponent : public Component,
  484. private ListBoxModel
  485. {
  486. public:
  487. TestListComponent (DemoHolderComponent& holder, ControllersComponent& controls)
  488. : demoHolder (holder)
  489. {
  490. demos.add (new PathsDemo (controls, false, true));
  491. demos.add (new PathsDemo (controls, true, false));
  492. demos.add (new PathsDemo (controls, false, false));
  493. demos.add (new RectangleFillTypesDemo (controls));
  494. demos.add (new StrokesDemo (controls));
  495. demos.add (new ImagesRenderingDemo (controls, false, false));
  496. demos.add (new ImagesRenderingDemo (controls, false, true));
  497. demos.add (new ImagesRenderingDemo (controls, true, false));
  498. demos.add (new ImagesRenderingDemo (controls, true, true));
  499. demos.add (new GlyphsDemo (controls));
  500. demos.add (new SVGDemo (controls));
  501. demos.add (new LinesDemo (controls));
  502. addAndMakeVisible (listBox);
  503. listBox.setModel (this);
  504. listBox.selectRow (0);
  505. listBox.setColour (ListBox::backgroundColourId, Colour::greyLevel (0.9f));
  506. }
  507. void resized()
  508. {
  509. listBox.setBounds (getLocalBounds());
  510. }
  511. int getNumRows()
  512. {
  513. return demos.size();
  514. }
  515. void paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected)
  516. {
  517. Component* demo = demos [rowNumber];
  518. if (demo != nullptr)
  519. {
  520. if (rowIsSelected)
  521. g.fillAll (findColour (TextEditor::highlightColourId));
  522. g.setColour (Colours::black);
  523. g.setFont (14.0f);
  524. g.drawFittedText (demo->getName(), 8, 0, width - 10, height, Justification::centredLeft, 2);
  525. }
  526. }
  527. void selectedRowsChanged (int lastRowSelected)
  528. {
  529. demoHolder.setDemo (demos [lastRowSelected]);
  530. }
  531. private:
  532. DemoHolderComponent& demoHolder;
  533. ListBox listBox;
  534. OwnedArray<GraphicsDemoBase> demos;
  535. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TestListComponent);
  536. };
  537. //==============================================================================
  538. class GraphicsDemo : public Component
  539. {
  540. public:
  541. GraphicsDemo()
  542. : testList (demoHolder, controllersComponent)
  543. {
  544. setOpaque (true);
  545. addAndMakeVisible (demoHolder);
  546. addAndMakeVisible (controllersComponent);
  547. addAndMakeVisible (performanceDisplay);
  548. addAndMakeVisible (testList);
  549. }
  550. void paint (Graphics& g)
  551. {
  552. g.fillAll (Colours::grey);
  553. }
  554. void resized() override
  555. {
  556. Rectangle<int> area (getLocalBounds());
  557. controllersComponent.setBounds (area.removeFromBottom (150));
  558. testList.setBounds (area.removeFromRight (150));
  559. demoHolder.setBounds (area);
  560. performanceDisplay.setBounds (area.removeFromTop (20).removeFromRight (100));
  561. }
  562. private:
  563. ControllersComponent controllersComponent;
  564. DemoHolderComponent demoHolder;
  565. Label performanceDisplay;
  566. TestListComponent testList;
  567. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GraphicsDemo);
  568. };
  569. // This static object will register this demo type in a global list of demos..
  570. static JuceDemoType<GraphicsDemo> demo ("20 Graphics: 2D Rendering");