| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE examples.
 -    Copyright (c) 2022 - Raw Material Software Limited
 - 
 -    The code included in this file is provided under the terms of the ISC license
 -    http://www.isc.org/downloads/software-support-policy/isc-license. Permission
 -    To use, copy, modify, and/or distribute this software for any purpose with or
 -    without fee is hereby granted provided that the above copyright notice and
 -    this permission notice appear in all copies.
 - 
 -    THE SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES,
 -    WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR
 -    PURPOSE, ARE DISCLAIMED.
 - 
 -   ==============================================================================
 - */
 - 
 - /*******************************************************************************
 -  The block below describes the properties of this PIP. A PIP is a short snippet
 -  of code that can be read by the Projucer and used to generate a JUCE project.
 - 
 -  BEGIN_JUCE_PIP_METADATA
 - 
 -  name:             GraphicsDemo
 -  version:          1.0.0
 -  vendor:           JUCE
 -  website:          http://juce.com
 -  description:      Showcases various graphics features.
 - 
 -  dependencies:     juce_core, juce_data_structures, juce_events, juce_graphics,
 -                    juce_gui_basics
 -  exporters:        xcode_mac, vs2022, linux_make, androidstudio, xcode_iphone
 - 
 -  moduleFlags:      JUCE_STRICT_REFCOUNTEDPOINTER=1
 - 
 -  type:             Component
 -  mainClass:        GraphicsDemo
 - 
 -  useLocalCopy:     1
 - 
 -  END_JUCE_PIP_METADATA
 - 
 - *******************************************************************************/
 - 
 - #pragma once
 - 
 - #include "../Assets/DemoUtilities.h"
 - 
 - //==============================================================================
 - /** Holds the various toggle buttons for the animation modes. */
 - class ControllersComponent final : public Component
 - {
 - public:
 -     ControllersComponent()
 -     {
 -         setOpaque (true);
 - 
 -         initialiseToggle (animatePosition, "Animate Position",  true);
 -         initialiseToggle (animateRotation, "Animate Rotation",  true);
 -         initialiseToggle (animateSize,     "Animate Size",      false);
 -         initialiseToggle (animateShear,    "Animate Shearing",  false);
 -         initialiseToggle (animateAlpha,    "Animate Alpha",     false);
 -         initialiseToggle (clipToRectangle, "Clip to Rectangle", false);
 -         initialiseToggle (clipToPath,      "Clip to Path",      false);
 -         initialiseToggle (clipToImage,     "Clip to Image",     false);
 -         initialiseToggle (quality,         "Higher quality image interpolation", false);
 -     }
 - 
 -     void paint (Graphics& g) override
 -     {
 -         g.fillAll (getUIColourIfAvailable (LookAndFeel_V4::ColourScheme::UIColour::windowBackground));
 -     }
 - 
 -     void resized() override
 -     {
 -         auto r = getLocalBounds().reduced (4);
 - 
 -         int buttonHeight = 22;
 - 
 -         auto columns = r.removeFromTop (buttonHeight * 4);
 -         auto col = columns.removeFromLeft (200);
 - 
 -         animatePosition.setBounds (col.removeFromTop (buttonHeight));
 -         animateRotation.setBounds (col.removeFromTop (buttonHeight));
 -         animateSize    .setBounds (col.removeFromTop (buttonHeight));
 -         animateShear   .setBounds (col.removeFromTop (buttonHeight));
 - 
 -         columns.removeFromLeft (20);
 -         col = columns.removeFromLeft (200);
 - 
 -         animateAlpha   .setBounds (col.removeFromTop (buttonHeight));
 -         clipToRectangle.setBounds (col.removeFromTop (buttonHeight));
 -         clipToPath     .setBounds (col.removeFromTop (buttonHeight));
 -         clipToImage    .setBounds (col.removeFromTop (buttonHeight));
 - 
 -         r.removeFromBottom (6);
 -         quality.setBounds (r.removeFromTop (buttonHeight));
 -     }
 - 
 -     void initialiseToggle (ToggleButton& b, const char* name, bool on)
 -     {
 -         addAndMakeVisible (b);
 -         b.setButtonText (name);
 -         b.setToggleState (on, dontSendNotification);
 -     }
 - 
 -     ToggleButton animateRotation, animatePosition, animateAlpha, animateSize, animateShear;
 -     ToggleButton clipToRectangle, clipToPath, clipToImage, quality;
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ControllersComponent)
 - };
 - 
 - //==============================================================================
 - class GraphicsDemoBase : public Component
 - {
 - public:
 -     GraphicsDemoBase (ControllersComponent& cc, const String& name)
 -         : Component (name),
 -           controls (cc)
 -     {
 -         displayFont = Font (Font::getDefaultMonospacedFontName(), 12.0f, Font::bold);
 -     }
 - 
 -     AffineTransform getTransform()
 -     {
 -         auto hw = 0.5f * (float) getWidth();
 -         auto hh = 0.5f * (float) getHeight();
 - 
 -         AffineTransform t;
 - 
 -         if (controls.animateRotation.getToggleState())
 -             t = t.rotated (rotation.getValue() * MathConstants<float>::twoPi);
 - 
 -         if (controls.animateSize.getToggleState())
 -             t = t.scaled (0.3f + size.getValue() * 2.0f);
 - 
 -         if (controls.animatePosition.getToggleState())
 -             t = t.translated (hw + hw * (offsetX.getValue() - 0.5f),
 -                               hh + hh * (offsetY.getValue() - 0.5f));
 -         else
 -             t = t.translated (hw, hh);
 - 
 -         if (controls.animateShear.getToggleState())
 -             t = t.sheared (shear.getValue() * 2.0f - 1.0f, 0.0f);
 - 
 -         return t;
 -     }
 - 
 -     float getAlpha() const
 -     {
 -         if (controls.animateAlpha.getToggleState())
 -             return alpha.getValue();
 - 
 -         return 1.0f;
 -     }
 - 
 -     void paint (Graphics& g) override
 -     {
 -         auto startTime = 0.0;
 - 
 -         {
 -             // A ScopedSaveState will return the Graphics context to the state it was at the time of
 -             // construction when it goes out of scope. We use it here to avoid clipping the fps text
 -             const Graphics::ScopedSaveState state (g);
 - 
 -             if (controls.clipToRectangle.getToggleState())  clipToRectangle (g);
 -             if (controls.clipToPath     .getToggleState())  clipToPath (g);
 -             if (controls.clipToImage    .getToggleState())  clipToImage (g);
 - 
 -             g.setImageResamplingQuality (controls.quality.getToggleState() ? Graphics::highResamplingQuality
 -                                                                            : Graphics::mediumResamplingQuality);
 - 
 -             // take a note of the time before the render
 -             startTime = Time::getMillisecondCounterHiRes();
 - 
 -             // then let the demo draw itself..
 -             drawDemo (g);
 -         }
 - 
 -         auto now = Time::getMillisecondCounterHiRes();
 -         auto filtering = 0.08;
 - 
 -         auto elapsedMs = now - startTime;
 -         averageTimeMs += (elapsedMs - averageTimeMs) * filtering;
 - 
 -         auto sinceLastRender = now - lastRenderStartTime;
 -         lastRenderStartTime = now;
 - 
 -         auto effectiveFPS = 1000.0 / averageTimeMs;
 -         auto actualFPS = sinceLastRender > 0 ? (1000.0 / sinceLastRender) : 0;
 -         averageActualFPS += (actualFPS - averageActualFPS) * filtering;
 - 
 -         GlyphArrangement ga;
 -         ga.addFittedText (displayFont,
 -                           "Time: " + String (averageTimeMs, 2)
 -                             + " ms\nEffective FPS: " + String (effectiveFPS, 1)
 -                             + "\nActual FPS: " + String (averageActualFPS, 1),
 -                           0, 10.0f, (float) getWidth() - 10.0f, (float) getHeight(), Justification::topRight, 3);
 - 
 -         g.setColour (Colours::white.withAlpha (0.5f));
 -         g.fillRect (ga.getBoundingBox (0, ga.getNumGlyphs(), true).getSmallestIntegerContainer().expanded (4));
 - 
 -         g.setColour (Colours::black);
 -         ga.draw (g);
 -     }
 - 
 -     virtual void drawDemo (Graphics&) = 0;
 - 
 -     void clipToRectangle (Graphics& g)
 -     {
 -         auto w = getWidth()  / 2;
 -         auto h = getHeight() / 2;
 - 
 -         auto x = (int) ((float) w * clipRectX.getValue());
 -         auto y = (int) ((float) h * clipRectY.getValue());
 - 
 -         g.reduceClipRegion (x, y, w, h);
 -     }
 - 
 -     void clipToPath (Graphics& g)
 -     {
 -         auto pathSize = (float) jmin (getWidth(), getHeight());
 - 
 -         Path p;
 -         p.addStar (Point<float> (clipPathX.getValue(),
 -                                  clipPathY.getValue()) * pathSize,
 -                    7,
 -                    pathSize * (0.5f + clipPathDepth.getValue()),
 -                    pathSize * 0.5f,
 -                    clipPathAngle.getValue());
 - 
 -         g.reduceClipRegion (p, AffineTransform());
 -     }
 - 
 -     void clipToImage (Graphics& g)
 -     {
 -         if (! clipImage.isValid())
 -             createClipImage();
 - 
 -         AffineTransform transform (AffineTransform::translation ((float) clipImage.getWidth()  / -2.0f,
 -                                                                  (float) clipImage.getHeight() / -2.0f)
 -                                    .rotated (clipImageAngle.getValue() * MathConstants<float>::twoPi)
 -                                    .scaled (2.0f + clipImageSize.getValue() * 3.0f)
 -                                    .translated ((float) getWidth()  * 0.5f,
 -                                                 (float) getHeight() * 0.5f));
 - 
 -         g.reduceClipRegion (clipImage, transform);
 -     }
 - 
 -     void createClipImage()
 -     {
 -         clipImage = Image (Image::ARGB, 300, 300, true);
 - 
 -         Graphics g (clipImage);
 - 
 -         g.setGradientFill (ColourGradient (Colours::transparentBlack, 0, 0,
 -                                            Colours::black, 0, 300, false));
 - 
 -         for (int i = 0; i < 20; ++i)
 -             g.fillRect (Random::getSystemRandom().nextInt (200),
 -                         Random::getSystemRandom().nextInt (200),
 -                         Random::getSystemRandom().nextInt (100),
 -                         Random::getSystemRandom().nextInt (100));
 -     }
 - 
 -     //==============================================================================
 -     ControllersComponent& controls;
 - 
 -     SlowerBouncingNumber offsetX, offsetY, rotation, size, shear, alpha, clipRectX,
 -                          clipRectY, clipPathX, clipPathY, clipPathDepth, clipPathAngle,
 -                          clipImageX, clipImageY, clipImageAngle, clipImageSize;
 - 
 -     double lastRenderStartTime = 0.0, averageTimeMs = 0.0, averageActualFPS = 0.0;
 -     Image clipImage;
 -     Font displayFont;
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GraphicsDemoBase)
 - };
 - 
 - //==============================================================================
 - class RectangleFillTypesDemo final : public GraphicsDemoBase
 - {
 - public:
 -     RectangleFillTypesDemo (ControllersComponent& cc)
 -         : GraphicsDemoBase (cc, "Fill Types: Rectangles")
 -     {}
 - 
 -     void drawDemo (Graphics& g) override
 -     {
 -         g.addTransform (getTransform());
 - 
 -         const int rectSize = jmin (getWidth(), getHeight()) / 2 - 20;
 - 
 -         g.setColour (colour1.withAlpha (getAlpha()));
 -         g.fillRect (-rectSize, -rectSize, rectSize, rectSize);
 - 
 -         g.setGradientFill (ColourGradient (colour1, 10.0f, (float) -rectSize,
 -                                            colour2, 10.0f + (float) rectSize, 0.0f, false));
 -         g.setOpacity (getAlpha());
 -         g.fillRect (10, -rectSize, rectSize, rectSize);
 - 
 -         g.setGradientFill (ColourGradient (colour1, (float) rectSize * -0.5f, 10.0f + (float) rectSize * 0.5f,
 -                                            colour2, 0, 10.0f + (float) rectSize, true));
 -         g.setOpacity (getAlpha());
 -         g.fillRect (-rectSize, 10, rectSize, rectSize);
 - 
 -         g.setGradientFill (ColourGradient (colour1, 10.0f, 10.0f,
 -                                            colour2, 10.0f + (float) rectSize, 10.0f + (float) rectSize, false));
 -         g.setOpacity (getAlpha());
 -         g.drawRect (10, 10, rectSize, rectSize, 5);
 -     }
 - 
 -     Colour colour1 { Colours::red }, colour2 { Colours::green };
 - };
 - 
 - //==============================================================================
 - class PathsDemo final : public GraphicsDemoBase
 - {
 - public:
 -     PathsDemo (ControllersComponent& cc, bool linear, bool radial)
 -         : GraphicsDemoBase (cc, String ("Paths") + (radial ? ": Radial Gradients"
 -                                                            : (linear ? ": Linear Gradients"
 -                                                                      : ": Solid"))),
 -           useLinearGradient (linear), useRadialGradient (radial)
 -     {
 -         logoPath = getJUCELogoPath();
 - 
 -         // rescale the logo path so that it's centred about the origin and has the right size.
 -         logoPath.applyTransform (RectanglePlacement (RectanglePlacement::centred)
 -                                  .getTransformToFit (logoPath.getBounds(),
 -                                                      Rectangle<float> (-120.0f, -120.0f, 240.0f, 240.0f)));
 - 
 -         // Surround it with some other shapes..
 -         logoPath.addStar ({ -300.0f, -50.0f }, 7, 30.0f, 70.0f, 0.1f);
 -         logoPath.addStar ({ 300.0f, 50.0f }, 6, 40.0f, 70.0f, 0.1f);
 -         logoPath.addEllipse (-100.0f, 150.0f, 200.0f, 140.0f);
 -         logoPath.addRectangle (-100.0f, -280.0f, 200.0f, 140.0f);
 -     }
 - 
 -     void drawDemo (Graphics& g) override
 -     {
 -         auto& p = logoPath;
 - 
 -         if (useLinearGradient || useRadialGradient)
 -         {
 -             Colour c1 (gradientColours[0].getValue(), gradientColours[1].getValue(), gradientColours[2].getValue(), 1.0f);
 -             Colour c2 (gradientColours[3].getValue(), gradientColours[4].getValue(), gradientColours[5].getValue(), 1.0f);
 -             Colour c3 (gradientColours[6].getValue(), gradientColours[7].getValue(), gradientColours[8].getValue(), 1.0f);
 - 
 -             auto x1 = gradientPositions[0].getValue() * (float) getWidth()  * 0.25f;
 -             auto y1 = gradientPositions[1].getValue() * (float) getHeight() * 0.25f;
 -             auto x2 = gradientPositions[2].getValue() * (float) getWidth()  * 0.75f;
 -             auto y2 = gradientPositions[3].getValue() * (float) getHeight() * 0.75f;
 - 
 -             ColourGradient gradient (c1, x1, y1,
 -                                      c2, x2, y2,
 -                                      useRadialGradient);
 - 
 -             gradient.addColour (gradientIntermediate.getValue(), c3);
 - 
 -             g.setGradientFill (gradient);
 -         }
 -         else
 -         {
 -             g.setColour (Colours::blue);
 -         }
 - 
 -         g.setOpacity (getAlpha());
 -         g.fillPath (p, getTransform());
 -     }
 - 
 -     Path logoPath;
 -     bool useLinearGradient, useRadialGradient;
 -     SlowerBouncingNumber gradientColours[9], gradientPositions[4], gradientIntermediate;
 - };
 - 
 - //==============================================================================
 - class StrokesDemo final : public GraphicsDemoBase
 - {
 - public:
 -     StrokesDemo (ControllersComponent& cc)
 -         : GraphicsDemoBase (cc, "Paths: Stroked")
 -     {}
 - 
 -     void drawDemo (Graphics& g) override
 -     {
 -         auto w = (float) getWidth();
 -         auto h = (float) getHeight();
 - 
 -         Path p;
 -         p.startNewSubPath (points[0].getValue() * w,
 -                            points[1].getValue() * h);
 - 
 -         for (int i = 2; i < numElementsInArray (points); i += 4)
 -             p.quadraticTo (points[i]    .getValue() * w,
 -                            points[i + 1].getValue() * h,
 -                            points[i + 2].getValue() * w,
 -                            points[i + 3].getValue() * h);
 - 
 -         p.closeSubPath();
 - 
 -         PathStrokeType stroke (0.5f + 10.0f * thickness.getValue());
 -         g.setColour (Colours::purple.withAlpha (getAlpha()));
 -         g.strokePath (p, stroke, AffineTransform());
 -     }
 - 
 -     SlowerBouncingNumber points[2 + 4 * 8], thickness;
 - };
 - 
 - //==============================================================================
 - class ImagesRenderingDemo final : public GraphicsDemoBase
 - {
 - public:
 -     ImagesRenderingDemo (ControllersComponent& cc, bool argb, bool tiled)
 -         : GraphicsDemoBase (cc, String ("Images") + (argb ? ": ARGB" : ": RGB") + (tiled ? " Tiled" : String() )),
 -           isArgb (argb), isTiled (tiled)
 -     {
 -         argbImage = getImageFromAssets ("juce_icon.png");
 -         rgbImage  = getImageFromAssets ("portmeirion.jpg");
 -     }
 - 
 -     void drawDemo (Graphics& g) override
 -     {
 -         auto image = isArgb ? argbImage : rgbImage;
 - 
 -         AffineTransform transform (AffineTransform::translation ((float) (image.getWidth()  / -2),
 -                                                                  (float) (image.getHeight() / -2))
 -                                    .followedBy (getTransform()));
 - 
 -         if (isTiled)
 -         {
 -             FillType fill (image, transform);
 -             fill.setOpacity (getAlpha());
 -             g.setFillType (fill);
 -             g.fillAll();
 -         }
 -         else
 -         {
 -             g.setOpacity (getAlpha());
 -             g.drawImageTransformed (image, transform, false);
 -         }
 -     }
 - 
 -     bool isArgb, isTiled;
 -     Image rgbImage, argbImage;
 - };
 - 
 - //==============================================================================
 - class GlyphsDemo final : public GraphicsDemoBase
 - {
 - public:
 -     GlyphsDemo (ControllersComponent& cc)
 -         : GraphicsDemoBase (cc, "Glyphs")
 -     {
 -         glyphs.addFittedText ({ 20.0f }, "The Quick Brown Fox Jumped Over The Lazy Dog",
 -                               -120, -50, 240, 100, Justification::centred, 2, 1.0f);
 -     }
 - 
 -     void drawDemo (Graphics& g) override
 -     {
 -         g.setColour (Colours::black.withAlpha (getAlpha()));
 -         glyphs.draw (g, getTransform());
 -     }
 - 
 -     GlyphArrangement glyphs;
 - };
 - 
 - //==============================================================================
 - class SVGDemo final : public GraphicsDemoBase
 - {
 - public:
 -     SVGDemo (ControllersComponent& cc)
 -         : GraphicsDemoBase (cc, "SVG")
 -     {
 -         createSVGDrawable();
 -     }
 - 
 -     void drawDemo (Graphics& g) override
 -     {
 -         if (Time::getCurrentTime().toMilliseconds() > lastSVGLoadTime.toMilliseconds() + 2000)
 -             createSVGDrawable();
 - 
 -         svgDrawable->draw (g, getAlpha(), getTransform());
 -     }
 - 
 -     void createSVGDrawable()
 -     {
 -         lastSVGLoadTime = Time::getCurrentTime();
 - 
 -         ZipFile icons (createAssetInputStream ("icons.zip").release(), true);
 - 
 -         // Load a random SVG file from our embedded icons.zip file.
 -         const std::unique_ptr<InputStream> svgFileStream (icons.createStreamForEntry (Random::getSystemRandom().nextInt (icons.getNumEntries())));
 - 
 -         if (svgFileStream.get() != nullptr)
 -         {
 -             svgDrawable = Drawable::createFromImageDataStream (*svgFileStream);
 - 
 -             if (svgDrawable != nullptr)
 -             {
 -                 // to make our icon the right size, we'll set its bounding box to the size and position that we want.
 - 
 -                 if (auto comp = dynamic_cast<DrawableComposite*> (svgDrawable.get()))
 -                     comp->setBoundingBox ({ -100.0f, -100.0f, 200.0f, 200.0f });
 -             }
 -         }
 -     }
 - 
 -     Time lastSVGLoadTime;
 -     std::unique_ptr<Drawable> svgDrawable;
 - };
 - 
 - //==============================================================================
 - class LinesDemo final : public GraphicsDemoBase
 - {
 - public:
 -     LinesDemo (ControllersComponent& cc)
 -         : GraphicsDemoBase (cc, "Lines")
 -     {}
 - 
 -     void drawDemo (Graphics& g) override
 -     {
 -         {
 -             RectangleList<float> verticalLines;
 -             verticalLines.ensureStorageAllocated (getWidth());
 - 
 -             auto pos = offset.getValue();
 - 
 -             for (int x = 0; x < getWidth(); ++x)
 -             {
 -                 auto y = (float) getHeight() * 0.3f;
 -                 auto length = y * std::abs (std::sin ((float) x / 100.0f + 2.0f * pos));
 -                 verticalLines.addWithoutMerging (Rectangle<float> ((float) x, y - length * 0.5f, 1.0f, length));
 -             }
 - 
 -             g.setColour (Colours::blue.withAlpha (getAlpha()));
 -             g.fillRectList (verticalLines);
 -         }
 - 
 -         {
 -             RectangleList<float> horizontalLines;
 -             horizontalLines.ensureStorageAllocated (getHeight());
 - 
 -             auto pos = offset.getValue();
 - 
 -             for (int y = 0; y < getHeight(); ++y)
 -             {
 -                 auto x = (float) getWidth() * 0.3f;
 -                 auto length = x * std::abs (std::sin ((float) y / 100.0f + 2.0f * pos));
 -                 horizontalLines.addWithoutMerging (Rectangle<float> (x - length * 0.5f, (float) y, length, 1.0f));
 -             }
 - 
 -             g.setColour (Colours::green.withAlpha (getAlpha()));
 -             g.fillRectList (horizontalLines);
 -         }
 - 
 -         g.setColour (Colours::red.withAlpha (getAlpha()));
 - 
 -         auto w = (float) getWidth();
 -         auto h = (float) getHeight();
 - 
 -         g.drawLine (positions[0].getValue() * w,
 -                     positions[1].getValue() * h,
 -                     positions[2].getValue() * w,
 -                     positions[3].getValue() * h);
 - 
 -         g.drawLine (positions[4].getValue() * w,
 -                     positions[5].getValue() * h,
 -                     positions[6].getValue() * w,
 -                     positions[7].getValue() * h);
 -     }
 - 
 -     SlowerBouncingNumber offset, positions[8];
 - };
 - 
 - //==============================================================================
 - class DemoHolderComponent final : public Component,
 -                                   private Timer
 - {
 - public:
 -     DemoHolderComponent()
 -     {
 -         setOpaque (true);
 -     }
 - 
 -     void paint (Graphics& g) override
 -     {
 -         g.fillCheckerBoard (getLocalBounds().toFloat(), 48.0f, 48.0f,
 -                             Colours::lightgrey, Colours::white);
 -     }
 - 
 -     void timerCallback() override
 -     {
 -         if (currentDemo != nullptr)
 -             currentDemo->repaint();
 -     }
 - 
 -     void setDemo (GraphicsDemoBase* newDemo)
 -     {
 -         if (currentDemo != nullptr)
 -             removeChildComponent (currentDemo);
 - 
 -         currentDemo = newDemo;
 - 
 -         if (currentDemo != nullptr)
 -         {
 -             addAndMakeVisible (currentDemo);
 -             startTimerHz (60);
 -             resized();
 -         }
 -     }
 - 
 -     void resized() override
 -     {
 -         if (currentDemo != nullptr)
 -             currentDemo->setBounds (getLocalBounds());
 -     }
 - 
 - private:
 -     GraphicsDemoBase* currentDemo = nullptr;
 - };
 - 
 - //==============================================================================
 - class TestListComponent final : public Component,
 -                                 private ListBoxModel
 - {
 - public:
 -     TestListComponent (DemoHolderComponent& holder, ControllersComponent& controls)
 -         : demoHolder (holder)
 -     {
 -         demos.add (new PathsDemo (controls, false, true));
 -         demos.add (new PathsDemo (controls, true,  false));
 -         demos.add (new PathsDemo (controls, false, false));
 -         demos.add (new RectangleFillTypesDemo (controls));
 -         demos.add (new StrokesDemo (controls));
 -         demos.add (new ImagesRenderingDemo (controls, false, false));
 -         demos.add (new ImagesRenderingDemo (controls, false, true));
 -         demos.add (new ImagesRenderingDemo (controls, true,  false));
 -         demos.add (new ImagesRenderingDemo (controls, true,  true));
 -         demos.add (new GlyphsDemo (controls));
 -         demos.add (new SVGDemo    (controls));
 -         demos.add (new LinesDemo  (controls));
 - 
 -         addAndMakeVisible (listBox);
 -         listBox.setTitle ("Test List");
 -         listBox.setModel (this);
 -         listBox.selectRow (0);
 -     }
 - 
 -     void resized() override
 -     {
 -         listBox.setBounds (getLocalBounds());
 -     }
 - 
 -     int getNumRows() override
 -     {
 -         return demos.size();
 -     }
 - 
 -     void paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected) override
 -     {
 -         if (demos[rowNumber] == nullptr)
 -             return;
 - 
 -         if (rowIsSelected)
 -             g.fillAll (Colour::contrasting (findColour (ListBox::textColourId),
 -                                             findColour (ListBox::backgroundColourId)));
 - 
 -         g.setColour (findColour (ListBox::textColourId));
 -         g.setFont (14.0f);
 -         g.drawFittedText (getNameForRow (rowNumber), 8, 0, width - 10, height, Justification::centredLeft, 2);
 -     }
 - 
 -     String getNameForRow (int rowNumber) override
 -     {
 -         if (auto* demo = demos[rowNumber])
 -             return demo->getName();
 - 
 -         return {};
 -     }
 - 
 -     void selectedRowsChanged (int lastRowSelected) override
 -     {
 -         demoHolder.setDemo (demos [lastRowSelected]);
 -     }
 - 
 - private:
 -     DemoHolderComponent& demoHolder;
 -     ListBox listBox;
 -     OwnedArray<GraphicsDemoBase> demos;
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TestListComponent)
 - };
 - 
 - //==============================================================================
 - class GraphicsDemo final : public Component
 - {
 - public:
 -     GraphicsDemo()
 -         : testList (demoHolder, controllersComponent)
 -     {
 -         setOpaque (true);
 - 
 -         addAndMakeVisible (demoHolder);
 -         addAndMakeVisible (controllersComponent);
 -         addAndMakeVisible (performanceDisplay);
 -         addAndMakeVisible (testList);
 - 
 -         setSize (750, 750);
 -     }
 - 
 -     void paint (Graphics& g) override
 -     {
 -         g.fillAll (Colours::grey);
 -     }
 - 
 -     void resized() override
 -     {
 -         auto area = getLocalBounds();
 - 
 -         controllersComponent.setBounds (area.removeFromBottom (150));
 -         testList            .setBounds (area.removeFromRight (150));
 -         demoHolder          .setBounds (area);
 -         performanceDisplay  .setBounds (area.removeFromTop (20).removeFromRight (100));
 -     }
 - 
 - private:
 -     ControllersComponent controllersComponent;
 -     DemoHolderComponent demoHolder;
 -     Label performanceDisplay;
 -     TestListComponent testList;
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GraphicsDemo)
 - };
 
 
  |