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.

715 lines
25KB

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