| 
							- /*
 -   ==============================================================================
 - 
 -    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:             AccessibilityDemo
 -  version:          1.0.0
 -  vendor:           JUCE
 -  website:          http://juce.com
 -  description:      Simple UI demonstrating accessibility features on supported
 -                    platforms.
 - 
 -  dependencies:     juce_core, juce_data_structures, juce_events, juce_graphics,
 -                    juce_gui_basics
 -  exporters:        xcode_mac, vs2022, androidstudio, xcode_iphone
 - 
 -  moduleFlags:      JUCE_STRICT_REFCOUNTEDPOINTER=1
 - 
 -  type:             Component
 -  mainClass:        AccessibilityDemo
 - 
 -  useLocalCopy:     1
 - 
 -  END_JUCE_PIP_METADATA
 - 
 - *******************************************************************************/
 - 
 - #pragma once
 - 
 - #include "../Assets/DemoUtilities.h"
 - 
 - //==============================================================================
 - /**
 -     A simple holder component with some content, a title and an info tooltip
 -     containing a brief description.
 - 
 -     This component sets its accessibility title and help text properties and
 -     also acts as a focus container for its children.
 - */
 - class ContentComponent  : public Component
 - {
 - public:
 -     ContentComponent (const String& title, const String& info, Component& contentToDisplay)
 -          : titleLabel ({}, title),
 -            content (contentToDisplay)
 -     {
 -         addAndMakeVisible (titleLabel);
 -         addAndMakeVisible (infoIcon);
 - 
 -         setTitle (title);
 -         setDescription (info);
 -         setFocusContainerType (FocusContainerType::focusContainer);
 - 
 -         infoIcon.setTooltip (info);
 -         infoIcon.setHelpText (info);
 - 
 -         addAndMakeVisible (content);
 -     }
 - 
 -     void paint (Graphics& g) override
 -     {
 -         g.setColour (Colours::black);
 -         g.drawRoundedRectangle (getLocalBounds().reduced (2).toFloat(), 5.0f, 3.0f);
 -     }
 - 
 -     void resized() override
 -     {
 -         auto bounds = getLocalBounds().reduced (5);
 - 
 -         auto topArea = bounds.removeFromTop (30);
 -         infoIcon.setBounds (topArea.removeFromLeft (30).reduced (5));
 -         titleLabel.setBounds (topArea.reduced (5));
 - 
 -         content.setBounds (bounds);
 -     }
 - 
 - private:
 -     //==============================================================================
 -     struct InfoIcon  : public Component,
 -                        public SettableTooltipClient
 -     {
 -         InfoIcon()
 -         {
 -             constexpr uint8 infoPathData[] =
 -             {
 -               110,109,0,0,122,67,0,0,0,0,98,79,35,224,66,0,0,0,0,0,0,0,0,79,35,224,66,0,0,0,0,0,0,122,67,98,0,0,
 -               0,0,44,247,193,67,79,35,224,66,0,0,250,67,0,0,122,67,0,0,250,67,98,44,247,193,67,0,0,250,67,0,0,
 -               250,67,44,247,193,67,0,0,250,67,0,0,122,67,98,0,0,250,67,79,35,224,66,44,247,193,67,0,0,0,0,0,0,122,
 -               67,0,0,0,0,99,109,114,79,101,67,79,35,224,66,108,71,88,135,67,79,35,224,66,108,71,88,135,67,132,229,
 -               28,67,108,116,79,101,67,132,229,28,67,108,116,79,101,67,79,35,224,66,99,109,79,35,149,67,106,132,
 -               190,67,108,98,185,123,67,106,132,190,67,98,150,123,106,67,106,132,190,67,176,220,97,67,168,17,187,
 -               67,176,220,97,67,18,150,177,67,108,176,220,97,67,248,52,108,67,98,176,220,97,67,212,8,103,67,238,
 -               105,94,67,18,150,99,67,204,61,89,67,18,150,99,67,108,98,185,73,67,18,150,99,67,108,98,185,73,67,88,
 -               238,59,67,108,160,70,120,67,88,238,59,67,98,54,194,132,67,88,238,59,67,169,17,137,67,60,141,68,67,
 -               169,17,137,67,8,203,85,67,108,169,17,137,67,26,97,166,67,98,169,17,137,67,43,247,168,67,10,203,138,
 -               67,141,176,170,67,27,97,141,67,141,176,170,67,108,80,35,149,67,141,176,170,67,108,80,35,149,67,106,
 -               132,190,67,99,101,0,0
 -             };
 - 
 -             infoPath.loadPathFromData (infoPathData, numElementsInArray (infoPathData));
 - 
 -             setTitle ("Info");
 -         }
 - 
 -         void paint (Graphics& g) override
 -         {
 -             auto bounds = getLocalBounds().toFloat().reduced (2);
 - 
 -             g.setColour (Colours::white);
 -             g.fillPath (infoPath, RectanglePlacement (RectanglePlacement::centred)
 -                                     .getTransformToFit (infoPath.getBounds(), bounds));
 -         }
 - 
 -         Path infoPath;
 -     };
 - 
 -     //==============================================================================
 -     Label titleLabel;
 -     InfoIcon infoIcon;
 -     Component& content;
 - 
 -     //==============================================================================
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ContentComponent)
 - };
 - 
 - //==============================================================================
 - /**
 -     The top-level component containing the accessible JUCE widget examples.
 - 
 -     Most JUCE UI elements have built-in accessibility support and will be
 -     visible and controllable by accessibility clients. There are a few examples
 -     of some widgets in this demo such as Sliders, Buttons and a TreeView.
 - */
 - class JUCEWidgetsComponent  : public Component
 - {
 - public:
 -     JUCEWidgetsComponent()
 -     {
 -         setTitle ("JUCE Widgets");
 -         setDescription ("A demo of a few of the accessible built-in JUCE widgets.");
 -         setFocusContainerType (FocusContainerType::focusContainer);
 - 
 -         addAndMakeVisible (descriptionLabel);
 - 
 -         addAndMakeVisible (buttons);
 -         addAndMakeVisible (sliders);
 -         addAndMakeVisible (treeView);
 -     }
 - 
 -     void resized() override
 -     {
 -         Grid grid;
 - 
 -         grid.templateRows = { Grid::TrackInfo (Grid::Fr (1)), Grid::TrackInfo (Grid::Fr (1)), Grid::TrackInfo (Grid::Fr (2)) };
 -         grid.templateColumns = { Grid::TrackInfo (Grid::Fr (1)), Grid::TrackInfo (Grid::Fr (1)) };
 - 
 -         grid.items = { GridItem (descriptionLabel).withMargin ({ 2 }).withColumn ({ GridItem::Span (2), {} }),
 -                        GridItem (buttons).withMargin ({ 2 }),
 -                        GridItem (sliders).withMargin ({ 2 }),
 -                        GridItem (treeView).withMargin ({ 2 }).withColumn ({ GridItem::Span (2), {} }) };
 - 
 -         grid.performLayout (getLocalBounds());
 -     }
 - 
 - private:
 -     //==============================================================================
 -     class ButtonsComponent  : public Component
 -     {
 -     public:
 -         ButtonsComponent()
 -         {
 -             addAndMakeVisible (radioButtons);
 - 
 -             textButton.setHasFocusOutline (true);
 -             addAndMakeVisible (textButton);
 - 
 -             shapeButton.setShape (getJUCELogoPath(), false, true, false);
 -             shapeButton.onClick = [] { AlertWindow::showMessageBoxAsync (MessageBoxIconType::InfoIcon, "Alert", "This is an AlertWindow"); };
 -             shapeButton.setHasFocusOutline (true);
 -             addAndMakeVisible (shapeButton);
 -         }
 - 
 -         void resized() override
 -         {
 -             auto bounds = getLocalBounds();
 - 
 -             radioButtons.setBounds (bounds.removeFromLeft (bounds.getWidth() / 2).reduced (5));
 -             textButton.setBounds (bounds.removeFromTop (bounds.getHeight() / 2).reduced (5));
 -             shapeButton.setBounds (bounds.reduced (5));
 -         }
 - 
 -     private:
 -         //==============================================================================
 -         struct RadioButtonsGroupComponent  : public Component
 -         {
 -             RadioButtonsGroupComponent()
 -             {
 -                 int index = 1;
 -                 for (auto& b : radioButtons)
 -                 {
 -                     b.setRadioGroupId (1);
 -                     b.setButtonText ("Button " + String (index++));
 -                     b.setHasFocusOutline (true);
 -                     addAndMakeVisible (b);
 -                 }
 - 
 -                 radioButtons[(size_t) Random::getSystemRandom().nextInt (numRadioButtons)].setToggleState (true, dontSendNotification);
 - 
 -                 setTitle ("Radio Buttons Group");
 -                 setFocusContainerType (FocusContainerType::focusContainer);
 -             }
 - 
 -             void resized() override
 -             {
 -                 auto bounds = getLocalBounds();
 -                 const auto height = bounds.getHeight() / numRadioButtons;
 - 
 -                 for (auto& b : radioButtons)
 -                     b.setBounds (bounds.removeFromTop (height).reduced (2));
 -             }
 - 
 -             static constexpr int numRadioButtons = 3;
 -             std::array<ToggleButton, numRadioButtons> radioButtons;
 -         };
 - 
 -         //==============================================================================
 -         RadioButtonsGroupComponent radioButtons;
 -         TextButton textButton { "Press me!" };
 -         ShapeButton shapeButton { "Pressable JUCE Logo",
 -                                   Colours::darkorange,
 -                                   Colours::darkorange.brighter (0.5f),
 -                                   Colours::darkorange.brighter (0.75f) };
 - 
 -         //==============================================================================
 -         JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ButtonsComponent)
 -     };
 - 
 -     //==============================================================================
 -     class SlidersComponent  : public Component
 -     {
 -     public:
 -         SlidersComponent()
 -         {
 -             auto setUpSlider = [this] (Slider& slider, Slider::SliderStyle style,
 -                                        double start, double end, double interval)
 -             {
 -                 slider.setSliderStyle (style);
 -                 slider.setRange (start, end, interval);
 - 
 -                 if (style != Slider::IncDecButtons)
 -                     slider.setTextBoxStyle (Slider::NoTextBox, false, 0, 0);
 - 
 -                 slider.setValue (start + (end - start) * Random::getSystemRandom().nextDouble());
 - 
 -                 addAndMakeVisible (slider);
 -             };
 - 
 -             setUpSlider (horizontalSlider, Slider::LinearHorizontal, 1.0, 100.0, 1.0);
 -             setUpSlider (incDecSlider, Slider::IncDecButtons, 1.0, 10.0, 1.0);
 - 
 -             for (auto& rotary : rotarySliders)
 -                 setUpSlider (rotary, Slider::Rotary, 1.0, 10.0, 1.0);
 -         }
 - 
 -         void resized() override
 -         {
 -             Grid grid;
 - 
 -             grid.templateRows = { Grid::TrackInfo (Grid::Fr (1)), Grid::TrackInfo (Grid::Fr (2)) };
 - 
 -             grid.templateColumns = { Grid::TrackInfo (Grid::Fr (1)),
 -                                      Grid::TrackInfo (Grid::Fr (1)),
 -                                      Grid::TrackInfo (Grid::Fr (1)) };
 - 
 -             grid.items = { GridItem (horizontalSlider).withMargin ({ 2 }).withColumn ({ GridItem::Span (2), {} }),
 -                            GridItem (incDecSlider).withMargin ({ 2 }) };
 - 
 -             for (auto& rotary : rotarySliders)
 -                 grid.items.add (GridItem (rotary).withMargin ({ 2 }));
 - 
 -             grid.performLayout (getLocalBounds());
 -         }
 - 
 -     private:
 -         Slider horizontalSlider, incDecSlider;
 -         std::array<Slider, 3> rotarySliders;
 - 
 -         //==============================================================================
 -         JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SlidersComponent)
 -     };
 - 
 -     //==============================================================================
 -     class TreeViewComponent  : public Component
 -     {
 -     public:
 -         TreeViewComponent()
 -         {
 -             tree.setRootItem (&root);
 -             tree.setRootItemVisible (false);
 - 
 -             addAndMakeVisible (tree);
 -         }
 - 
 -         void resized() override
 -         {
 -             tree.setBounds (getLocalBounds());
 -         }
 - 
 -     private:
 -         //==============================================================================
 -         struct RootItem  : public TreeViewItem
 -         {
 -             RootItem()
 -             {
 -                 struct Item  : public TreeViewItem
 -                 {
 -                     Item (int index, int depth, int numSubItems)
 -                         : textToDisplay ("Item " + String (index)
 -                                          + ". Depth: " + String (depth)
 -                                          + ". Num sub-items: " + String (numSubItems))
 -                     {
 -                         for (int i = 0; i < numSubItems; ++i)
 -                             addSubItem (new Item (i,
 -                                                   depth + 1,
 -                                                   Random::getSystemRandom().nextInt (jmax (0, 5 - depth))));
 -                     }
 - 
 -                     bool mightContainSubItems() override
 -                     {
 -                         return getNumSubItems() > 0;
 -                     }
 - 
 -                     void paintItem (Graphics& g, int width, int height) override
 -                     {
 -                         if (isSelected())
 -                         {
 -                             g.setColour (Colours::yellow.withAlpha (0.3f));
 -                             g.fillRect (0, 0, width, height);
 -                         }
 - 
 -                         g.setColour (Colours::black);
 -                         g.drawRect (0, height - 1, width, 1);
 - 
 -                         g.setColour (Colours::white);
 -                         g.drawText (textToDisplay, 0, 0, width, height, Justification::centredLeft);
 -                     }
 - 
 -                     String getAccessibilityName() override  { return textToDisplay; }
 - 
 -                     const String textToDisplay;
 -                 };
 - 
 -                 for (int i = 0; i < 10; ++i)
 -                     addSubItem (new Item (i, 0, Random::getSystemRandom().nextInt (10)));
 -             }
 - 
 -             bool mightContainSubItems() override
 -             {
 -                 return true;
 -             }
 -         };
 - 
 -         //==============================================================================
 -         TreeView tree;
 -         RootItem root;
 - 
 -         //==============================================================================
 -         JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TreeViewComponent)
 -     };
 - 
 -     //==============================================================================
 -     Label descriptionLabel { {}, "This is a demo of a few of the accessible built-in JUCE widgets.\n\n"
 -                                  "To navigate this demo with a screen reader, either enable VoiceOver on macOS and iOS, "
 -                                  "TalkBack on Android, or Narrator on Windows and follow the navigational prompts." };
 - 
 -     ButtonsComponent buttonsComponent;
 -     SlidersComponent slidersComponent;
 -     TreeViewComponent treeViewComponent;
 - 
 -     ContentComponent buttons { "Buttons",
 -                                "Examples of some JUCE buttons.",
 -                                buttonsComponent };
 -     ContentComponent sliders { "Sliders",
 -                                "Examples of some JUCE sliders.",
 -                                slidersComponent };
 -     ContentComponent treeView { "TreeView",
 -                                 "A JUCE TreeView.",
 -                                 treeViewComponent };
 - 
 -     //==============================================================================
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JUCEWidgetsComponent)
 - };
 - 
 - struct NameAndRole
 - {
 -     const char* name;
 -     AccessibilityRole role;
 - };
 - 
 - constexpr NameAndRole accessibilityRoles[]
 - {
 -     { "Ignored",       AccessibilityRole::ignored },
 -     { "Unspecified",   AccessibilityRole::unspecified },
 -     { "Button",        AccessibilityRole::button },
 -     { "Toggle",        AccessibilityRole::toggleButton },
 -     { "ComboBox",      AccessibilityRole::comboBox },
 -     { "Slider",        AccessibilityRole::slider },
 -     { "Static Text",   AccessibilityRole::staticText },
 -     { "Editable Text", AccessibilityRole::editableText },
 -     { "Image",         AccessibilityRole::image },
 -     { "Group",         AccessibilityRole::group },
 -     { "Window",        AccessibilityRole::window }
 - };
 - 
 - //==============================================================================
 - /**
 -     The top-level component containing a customisable accessible widget.
 - 
 -     The AccessibleComponent class just draws a JUCE logo and overrides the
 -     Component::createAccessibilityHandler() method to return a custom AccessibilityHandler.
 -     The properties of this handler are set by the various controls in the demo.
 - */
 - class CustomWidgetComponent  : public Component
 - {
 - public:
 -     CustomWidgetComponent()
 -     {
 -         setTitle ("Custom Widget");
 -         setDescription ("A demo of a customisable accessible widget.");
 -         setFocusContainerType (FocusContainerType::focusContainer);
 - 
 -         addAndMakeVisible (descriptionLabel);
 - 
 -         addAndMakeVisible (infoComponent);
 -         addAndMakeVisible (actionsComponent);
 -         addAndMakeVisible (valueInterfaceComponent);
 -         addAndMakeVisible (stateComponent);
 -         addAndMakeVisible (accessibleComponent);
 -     }
 - 
 -     void resized() override
 -     {
 -         Grid grid;
 - 
 -         grid.templateRows = { Grid::TrackInfo (Grid::Fr (1)),
 -                               Grid::TrackInfo (Grid::Fr (2)),
 -                               Grid::TrackInfo (Grid::Fr (2)),
 -                               Grid::TrackInfo (Grid::Fr (2)) };
 - 
 -         grid.templateColumns = { Grid::TrackInfo (Grid::Fr (1)), Grid::TrackInfo (Grid::Fr (1)) };
 - 
 -         grid.items = { GridItem (descriptionLabel).withMargin ({ 2 }).withColumn ({ GridItem::Span (2), {} }),
 -                        GridItem (infoComponent).withMargin ({ 2 }).withColumn ({ GridItem::Span (2), {} }),
 -                        GridItem (actionsComponent).withMargin ({ 2 }),
 -                        GridItem (valueInterfaceComponent).withMargin ({ 2 }),
 -                        GridItem (stateComponent).withMargin ({ 2 }),
 -                        GridItem (accessibleComponent).withMargin ({ 10 }) };
 - 
 -         grid.performLayout (getLocalBounds());
 -     }
 - 
 - private:
 -     //==============================================================================
 -     class AccessibleComponent  : public Component
 -     {
 -     public:
 -         explicit AccessibleComponent (CustomWidgetComponent& owner)
 -             : customWidgetComponent (owner)
 -         {
 -         }
 - 
 -         void paint (Graphics& g) override
 -         {
 -             g.setColour (Colours::darkorange);
 - 
 -             g.fillPath (juceLogoPath,
 -                         juceLogoPath.getTransformToScaleToFit (getLocalBounds().toFloat(), true));
 -         }
 - 
 -         std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override
 -         {
 -             /**
 -                 The AccessibilityHandler class is the interface between JUCE components
 -                 and accessibility clients. This derived class represents the properties
 -                 set via the demo UI.
 -             */
 -             struct CustomAccessibilityHandler  : public AccessibilityHandler
 -             {
 -                 explicit CustomAccessibilityHandler (CustomWidgetComponent& comp)
 -                     : AccessibilityHandler (comp.accessibleComponent,
 -                                             comp.infoComponent.getRole(),
 -                                             comp.actionsComponent.getActions(),
 -                                             { comp.valueInterfaceComponent.getValueInterface() }),
 -                       customWidgetComponent (comp)
 -                 {
 -                 }
 - 
 -                 String getTitle() const override                  { return customWidgetComponent.infoComponent.getTitle(); }
 -                 String getDescription() const override            { return customWidgetComponent.infoComponent.getDescription(); }
 -                 String getHelp() const override                   { return customWidgetComponent.infoComponent.getHelp(); }
 - 
 -                 AccessibleState getCurrentState() const override  { return customWidgetComponent.stateComponent.getAccessibleState(); }
 - 
 -                 CustomWidgetComponent& customWidgetComponent;
 -             };
 - 
 -             return std::make_unique<CustomAccessibilityHandler> (customWidgetComponent);
 -         }
 - 
 -     private:
 -         CustomWidgetComponent& customWidgetComponent;
 -         Path juceLogoPath { getJUCELogoPath() };
 - 
 -         //==============================================================================
 -         JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AccessibleComponent)
 -     };
 - 
 -     //==============================================================================
 -     class InfoComponent  : public Component
 -     {
 -     public:
 -         explicit InfoComponent (CustomWidgetComponent& owner)
 -         {
 -             titleEditor.setText ("Custom");
 -             descriptionEditor.setText ("A short description of the custom component.");
 -             helpEditor.setText ("Some help text for the custom component.");
 - 
 -             titleEditor.onTextChange = [&owner]
 -             {
 -                 if (auto* handler = owner.accessibleComponent.getAccessibilityHandler())
 -                     handler->notifyAccessibilityEvent (AccessibilityEvent::titleChanged);
 -             };
 - 
 -             for (auto* editor : { &descriptionEditor, &helpEditor })
 -             {
 -                 editor->setMultiLine (true);
 -                 editor->setReturnKeyStartsNewLine (true);
 -                 editor->setJustification (Justification::centredLeft);
 -             }
 - 
 -             addAndMakeVisible (titleLabel);
 -             addAndMakeVisible (titleEditor);
 - 
 -             addAndMakeVisible (descriptionLabel);
 -             addAndMakeVisible (descriptionEditor);
 - 
 -             addAndMakeVisible (helpLabel);
 -             addAndMakeVisible (helpEditor);
 - 
 -             setUpAccessibilityRoleSelector (owner);
 -             addAndMakeVisible (roleBox);
 -             addAndMakeVisible (roleLabel);
 -         }
 - 
 -         void resized() override
 -         {
 -             Grid grid;
 - 
 -             grid.templateRows = { Grid::TrackInfo (Grid::Fr (1)), Grid::TrackInfo (Grid::Fr (3)) };
 - 
 -             grid.templateColumns = { Grid::TrackInfo (Grid::Fr (1)),
 -                                      Grid::TrackInfo (Grid::Fr (1)),
 -                                      Grid::TrackInfo (Grid::Fr (1)),
 -                                      Grid::TrackInfo (Grid::Fr (1)),
 -                                      Grid::TrackInfo (Grid::Fr (1)),
 -                                      Grid::TrackInfo (Grid::Fr (1)) };
 - 
 -             grid.items = { GridItem (titleLabel).withMargin ({ 2 }),
 -                            GridItem (titleEditor).withMargin ({ 2 }).withColumn ({ GridItem::Span (2), {} }),
 - 
 -                            GridItem (roleLabel).withMargin ({ 2 }),
 -                            GridItem (roleBox).withMargin ({ 2 }).withColumn ({ GridItem::Span (2), {} }),
 - 
 -                            GridItem (descriptionLabel).withMargin ({ 2 }),
 -                            GridItem (descriptionEditor).withMargin ({ 2 }).withColumn ({ GridItem::Span (2), {} }),
 - 
 -                            GridItem (helpLabel).withMargin ({ 2 }),
 -                            GridItem (helpEditor).withMargin ({ 2 }).withColumn ({ GridItem::Span (2), {} }) };
 - 
 -             grid.performLayout (getLocalBounds());
 -         }
 - 
 -         AccessibilityRole getRole() const noexcept  { return accessibilityRoles[(size_t) roleBox.getSelectedItemIndex()].role; }
 - 
 -         String getTitle() const noexcept            { return titleEditor.getText(); }
 -         String getDescription() const noexcept      { return descriptionEditor.getText(); }
 -         String getHelp() const noexcept             { return helpEditor.getText(); }
 - 
 -     private:
 -         void setUpAccessibilityRoleSelector (CustomWidgetComponent& owner)
 -         {
 -             int itemId = 1;
 -             for (const auto& nameAndRole : accessibilityRoles)
 -                 roleBox.addItem (nameAndRole.name, itemId++);
 - 
 -             roleBox.setSelectedItemIndex (1);
 -             roleBox.onChange = [&owner] { owner.accessibleComponent.invalidateAccessibilityHandler(); };
 -         }
 - 
 -         //==============================================================================
 -         Label titleLabel { {}, "Title" }, descriptionLabel { {}, "Description" }, helpLabel { {}, "Help" };
 -         TextEditor titleEditor, descriptionEditor, helpEditor;
 - 
 -         Label roleLabel { {}, "Role" };
 -         ComboBox roleBox;
 - 
 -         //==============================================================================
 -         JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (InfoComponent)
 -     };
 - 
 -     //==============================================================================
 -     class ActionsComponent  : public Component
 -     {
 -     public:
 -         explicit ActionsComponent (CustomWidgetComponent& owner)
 -             : customWidgetComponent (owner)
 -         {
 -             addAndMakeVisible (press);
 -             addAndMakeVisible (toggle);
 -             addAndMakeVisible (focus);
 -             addAndMakeVisible (showMenu);
 -         }
 - 
 -         void resized() override
 -         {
 -             Grid grid;
 - 
 -             grid.templateRows = { Grid::TrackInfo (Grid::Fr (1)), Grid::TrackInfo (Grid::Fr (1)) };
 -             grid.templateColumns = { Grid::TrackInfo (Grid::Fr (1)), Grid::TrackInfo (Grid::Fr (1)) };
 - 
 -             grid.items = { GridItem (press).withMargin (2), GridItem (toggle).withMargin (2),
 -                            GridItem (focus).withMargin (2), GridItem (showMenu).withMargin (2), };
 - 
 -             grid.performLayout (getLocalBounds());
 -         }
 - 
 -         AccessibilityActions getActions() noexcept
 -         {
 -             AccessibilityActions result;
 - 
 -             if (press.isActionEnabled())     result.addAction (AccessibilityActionType::press,    [this] { press.onAction(); });
 -             if (toggle.isActionEnabled())    result.addAction (AccessibilityActionType::toggle,   [this] { toggle.onAction(); });
 -             if (focus.isActionEnabled())     result.addAction (AccessibilityActionType::focus,    [this] { focus.onAction(); });
 -             if (showMenu.isActionEnabled())  result.addAction (AccessibilityActionType::showMenu, [this] { showMenu.onAction(); });
 - 
 -             return result;
 -         }
 - 
 -     private:
 -         //==============================================================================
 -         class AccessibilityActionComponent  : public Component,
 -                                               private Timer
 -         {
 -         public:
 -             AccessibilityActionComponent (CustomWidgetComponent& owner,
 -                                           const String& actionName,
 -                                           bool initialState)
 -             {
 -                 enabledToggle.setButtonText (actionName);
 -                 enabledToggle.onClick = [&owner] { owner.accessibleComponent.invalidateAccessibilityHandler(); };
 -                 enabledToggle.setToggleState (initialState, dontSendNotification);
 - 
 -                 addAndMakeVisible (enabledToggle);
 -             }
 - 
 -             void resized() override
 -             {
 -                 auto bounds = getLocalBounds();
 - 
 -                 flashArea = bounds.removeFromRight (bounds.getHeight()).reduced (5);
 -                 bounds.removeFromRight (5);
 -                 enabledToggle.setBounds (bounds);
 -             }
 - 
 -             void paint (Graphics& g) override
 -             {
 -                 g.setColour (flashColour);
 -                 g.fillRoundedRectangle (flashArea.toFloat(), 5.0f);
 -             }
 - 
 -             void onAction()
 -             {
 -                 if (isTimerRunning())
 -                     reset();
 - 
 -                 startTime = Time::getMillisecondCounter();
 -                 startTimer (5);
 -             }
 - 
 -             bool isActionEnabled() const noexcept  { return enabledToggle.getToggleState(); }
 - 
 -         private:
 -             void timerCallback() override
 -             {
 -                 const auto alpha = [this]
 -                 {
 -                     const auto progress =  static_cast<float> (Time::getMillisecondCounter() - startTime) / (flashTimeMs / 2);
 - 
 -                     return progress > 1.0f ? 2.0f - progress
 -                                            : progress;
 -                 }();
 - 
 -                 if (alpha < 0.0f)
 -                 {
 -                     reset();
 -                     return;
 -                 }
 - 
 -                 flashColour = defaultColour.overlaidWith (Colours::yellow.withAlpha (alpha));
 -                 repaint();
 -             }
 - 
 -             void reset()
 -             {
 -                 stopTimer();
 -                 flashColour = defaultColour;
 -                 repaint();
 -             }
 - 
 -             //==============================================================================
 -             static constexpr int flashTimeMs = 500;
 - 
 -             ToggleButton enabledToggle;
 -             Rectangle<int> flashArea;
 -             uint32 startTime = 0;
 -             Colour defaultColour = Colours::lightgrey, flashColour = defaultColour;
 - 
 -             //==============================================================================
 -             JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AccessibilityActionComponent)
 -         };
 - 
 -         //==============================================================================
 -         CustomWidgetComponent& customWidgetComponent;
 - 
 -         AccessibilityActionComponent press    { customWidgetComponent, "Press",     true },
 -                                      toggle   { customWidgetComponent, "Toggle",    false },
 -                                      focus    { customWidgetComponent, "Focus",     true },
 -                                      showMenu { customWidgetComponent, "Show menu", false };
 - 
 -         //==============================================================================
 -         JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ActionsComponent)
 -     };
 - 
 -     //==============================================================================
 -     class ValueInterfaceComponent  : public Component
 -     {
 -     public:
 -         explicit ValueInterfaceComponent (CustomWidgetComponent& owner)
 -             : customWidgetComponent (owner)
 -         {
 -             valueTypeBox.addItemList ({ "Numeric", "Ranged", "Text" }, 1);
 -             valueTypeBox.setSelectedId (1);
 -             addAndMakeVisible (valueTypeBox);
 - 
 -             valueTypeBox.onChange = [this]
 -             {
 -                 updateValueUI();
 -                 customWidgetComponent.accessibleComponent.invalidateAccessibilityHandler();
 -             };
 - 
 -             addAndMakeVisible (readOnlyToggle);
 - 
 -             numericValueEditor.setInputRestrictions (10, "0123456789.");
 -             addChildComponent (numericValueEditor);
 - 
 -             addChildComponent (rangedValueComponent);
 -             addChildComponent (textValueEditor);
 - 
 -             updateValueUI();
 -         }
 - 
 -         void resized() override
 -         {
 -             Grid grid;
 - 
 -             grid.templateRows = { Grid::TrackInfo (Grid::Fr (1)), Grid::TrackInfo (Grid::Fr (2)) };
 -             grid.templateColumns = { Grid::TrackInfo (Grid::Fr (2)), Grid::TrackInfo (Grid::Fr (1)) };
 - 
 -             auto& valueEditComponent = [this]() -> Component&
 -             {
 -                 if (numericValueEditor.isVisible())    return numericValueEditor;
 -                 if (rangedValueComponent.isVisible())  return rangedValueComponent;
 -                 if (textValueEditor.isVisible())       return textValueEditor;
 - 
 -                 jassertfalse;
 -                 return numericValueEditor;
 -             }();
 - 
 -             grid.items = { GridItem (valueTypeBox).withMargin (2), GridItem (readOnlyToggle).withMargin (2),
 -                            GridItem (valueEditComponent).withMargin (2).withColumn ({ GridItem::Span (2), {} }), };
 - 
 -             grid.performLayout (getLocalBounds());
 -         }
 - 
 -         std::unique_ptr<AccessibilityValueInterface> getValueInterface()
 -         {
 -             struct Numeric  : public AccessibilityNumericValueInterface
 -             {
 -                 explicit Numeric (ValueInterfaceComponent& o)
 -                     : owner (o)
 -                 {
 -                 }
 - 
 -                 bool isReadOnly() const override          { return owner.readOnlyToggle.getToggleState(); }
 -                 double getCurrentValue() const override   { return owner.numericValueEditor.getText().getDoubleValue(); }
 -                 void setValue (double newValue) override  { owner.numericValueEditor.setText (String (newValue)); }
 - 
 -                 ValueInterfaceComponent& owner;
 -             };
 - 
 -             struct Ranged  : public AccessibilityRangedNumericValueInterface
 -             {
 -                 explicit Ranged (ValueInterfaceComponent& o)
 -                     : owner (o)
 -                 {
 -                 }
 - 
 -                 bool isReadOnly() const override                { return owner.readOnlyToggle.getToggleState(); }
 -                 double getCurrentValue() const override         { return owner.rangedValueComponent.valueSlider.getValue(); }
 -                 void setValue (double newValue) override        { owner.rangedValueComponent.valueSlider.setValue (newValue); }
 - 
 -                 AccessibleValueRange getRange() const override
 -                 {
 -                     const auto& slider = owner.rangedValueComponent.valueSlider;
 - 
 -                     return { { slider.getMinimum(), slider.getMaximum() },
 -                              slider.getInterval() };
 -                 }
 - 
 -                 ValueInterfaceComponent& owner;
 -             };
 - 
 -             struct Text  : public AccessibilityTextValueInterface
 -             {
 -                 explicit Text (ValueInterfaceComponent& o)
 -                     : owner (o)
 -                 {
 -                 }
 - 
 -                 bool isReadOnly() const override                         { return owner.readOnlyToggle.getToggleState(); }
 -                 String getCurrentValueAsString() const override          { return owner.textValueEditor.getText(); }
 -                 void setValueAsString (const String& newValue) override  { owner.textValueEditor.setText (newValue); }
 - 
 -                 ValueInterfaceComponent& owner;
 -             };
 - 
 -             const auto valueType = indexToValueType (valueTypeBox.getSelectedId());
 - 
 -             if (valueType == ValueType::numeric)  return std::make_unique<Numeric> (*this);
 -             if (valueType == ValueType::ranged)   return std::make_unique<Ranged>  (*this);
 -             if (valueType == ValueType::text)     return std::make_unique<Text>    (*this);
 - 
 -             jassertfalse;
 -             return nullptr;
 -         }
 - 
 -     private:
 -         //==============================================================================
 -         struct RangedValueComponent  : public Component
 -         {
 -             RangedValueComponent()
 -             {
 -                 const auto setUpNumericTextEditor = [this] (TextEditor& ed, double initialValue)
 -                 {
 -                     ed.setInputRestrictions (10, "0123456789.");
 -                     ed.setText (String (initialValue));
 -                     ed.onReturnKey = [this] { updateSliderRange(); };
 - 
 -                     addAndMakeVisible (ed);
 -                 };
 - 
 -                 setUpNumericTextEditor (minValueEditor,      0.0);
 -                 setUpNumericTextEditor (maxValueEditor,      10.0);
 -                 setUpNumericTextEditor (intervalValueEditor, 0.1);
 - 
 -                 addAndMakeVisible (minLabel);
 -                 addAndMakeVisible (maxLabel);
 -                 addAndMakeVisible (intervalLabel);
 - 
 -                 valueSlider.setSliderStyle (Slider::SliderStyle::LinearHorizontal);
 -                 addAndMakeVisible (valueSlider);
 -                 updateSliderRange();
 -             }
 - 
 -             void resized() override
 -             {
 -                 Grid grid;
 - 
 -                 grid.templateRows = { Grid::TrackInfo (Grid::Fr (2)), Grid::TrackInfo (Grid::Fr (3)), Grid::TrackInfo (Grid::Fr (3)) };
 -                 grid.templateColumns = { Grid::TrackInfo (Grid::Fr (1)), Grid::TrackInfo (Grid::Fr (1)), Grid::TrackInfo (Grid::Fr (1)) };
 - 
 -                 grid.items = { GridItem (minLabel).withMargin (2),       GridItem (maxLabel).withMargin (2),       GridItem (intervalLabel).withMargin (2),
 -                                GridItem (minValueEditor).withMargin (2), GridItem (maxValueEditor).withMargin (2), GridItem (intervalValueEditor).withMargin (2),
 -                                GridItem (valueSlider).withMargin (2).withColumn ({ GridItem::Span (3), {} }) };
 - 
 -                 grid.performLayout (getLocalBounds());
 -             }
 - 
 -             void updateSliderRange()
 -             {
 -                 auto minValue = minValueEditor.getText().getDoubleValue();
 -                 auto maxValue = maxValueEditor.getText().getDoubleValue();
 -                 const auto intervalValue = jmax (intervalValueEditor.getText().getDoubleValue(), 0.0001);
 - 
 -                 if (maxValue <= minValue)
 -                 {
 -                     maxValue = minValue + intervalValue;
 -                     maxValueEditor.setText (String (maxValue));
 -                 }
 -                 else if (minValue >= maxValue)
 -                 {
 -                     minValue = maxValue - intervalValue;
 -                     minValueEditor.setText (String (minValue));
 -                 }
 - 
 -                 valueSlider.setRange (minValue, maxValue, intervalValue);
 -             }
 - 
 -             Label minLabel { {}, "Min" }, maxLabel { {}, "Max" }, intervalLabel { {}, "Interval" };
 -             TextEditor minValueEditor, maxValueEditor, intervalValueEditor;
 -             Slider valueSlider;
 -         };
 - 
 -         //==============================================================================
 -         enum class ValueType { numeric, ranged, text };
 - 
 -         static ValueType indexToValueType (int index) noexcept
 -         {
 -             if (index == 1) return ValueType::numeric;
 -             if (index == 2) return ValueType::ranged;
 -             if (index == 3) return ValueType::text;
 - 
 -             jassertfalse;
 -             return ValueType::numeric;
 -         }
 - 
 -         void updateValueUI()
 -         {
 -             const auto valueType = indexToValueType (valueTypeBox.getSelectedId());
 - 
 -             numericValueEditor.setVisible (valueType == ValueType::numeric);
 -             textValueEditor.setVisible (valueType == ValueType::text);
 -             rangedValueComponent.setVisible (valueType == ValueType::ranged);
 - 
 -             resized();
 -         }
 - 
 -         //==============================================================================
 -         CustomWidgetComponent& customWidgetComponent;
 - 
 -         ComboBox valueTypeBox;
 -         ToggleButton readOnlyToggle { "Read-Only" };
 - 
 -         TextEditor numericValueEditor, textValueEditor;
 -         RangedValueComponent rangedValueComponent;
 - 
 -         //==============================================================================
 -         JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ValueInterfaceComponent)
 -     };
 - 
 -     //==============================================================================
 -     class StateComponent  : public Component
 -     {
 -     public:
 -         StateComponent()
 -         {
 -             for (auto& property : properties)
 -                 addAndMakeVisible (property.button);
 -         }
 - 
 -         void resized() override
 -         {
 -             Grid grid;
 - 
 -             grid.templateRows = { Grid::TrackInfo (Grid::Fr (1)),
 -                                   Grid::TrackInfo (Grid::Fr (1)),
 -                                   Grid::TrackInfo (Grid::Fr (1)),
 -                                   Grid::TrackInfo (Grid::Fr (1)),
 -                                   Grid::TrackInfo (Grid::Fr (1)),
 -                                   Grid::TrackInfo (Grid::Fr (1)) };
 - 
 -             grid.templateColumns = { Grid::TrackInfo (Grid::Fr (1)), Grid::TrackInfo (Grid::Fr (1)) };
 - 
 -             for (auto& property : properties)
 -                 grid.items.add (GridItem (property.button));
 - 
 -             grid.performLayout (getLocalBounds());
 -         }
 - 
 -         AccessibleState getAccessibleState() const
 -         {
 -             AccessibleState result;
 - 
 -             for (auto& property : properties)
 -                 if (property.button.getToggleState())
 -                     result = property.setState (std::move (result));
 - 
 -             return result;
 -         }
 - 
 -     private:
 -         struct Property
 -         {
 -             Property (const String& name,
 -                       bool initialState,
 -                       AccessibleState (AccessibleState::* fn)() const)
 -                 : button (name),
 -                   setStateFn (fn)
 -             {
 -                 button.setToggleState (initialState, dontSendNotification);
 -             }
 - 
 -             AccessibleState setState (AccessibleState s) const noexcept { return (s.*setStateFn)(); }
 - 
 -             ToggleButton button;
 -             AccessibleState (AccessibleState::* setStateFn)() const;
 -         };
 - 
 -         std::array<Property, 12> properties
 -         { {
 -             { "Checkable",            false, &AccessibleState::withCheckable },
 -             { "Checked",              false, &AccessibleState::withChecked },
 -             { "Collapsed",            false, &AccessibleState::withCollapsed },
 -             { "Expandable",           false, &AccessibleState::withExpandable },
 -             { "Expanded",             false, &AccessibleState::withExpanded },
 -             { "Focusable",            true,  &AccessibleState::withFocusable },
 -             { "Focused",              false, &AccessibleState::withFocused },
 -             { "Ignored",              false, &AccessibleState::withIgnored },
 -             { "Selectable",           false, &AccessibleState::withSelectable },
 -             { "Multi-Selectable",     false, &AccessibleState::withMultiSelectable },
 -             { "Selected",             false, &AccessibleState::withSelected },
 -             { "Accessible Offscreen", false, &AccessibleState::withAccessibleOffscreen }
 -         } };
 - 
 -         //==============================================================================
 -         JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StateComponent)
 -     };
 - 
 -     //==============================================================================
 -     Label descriptionLabel { {}, "This is a demo of a custom accessible widget.\n\n"
 -                                  "The JUCE logo component at the bottom of the page will use the settable properties when queried by "
 -                                  "an accessibility client." };
 - 
 -     InfoComponent infoComponent                     { *this };
 -     ActionsComponent actionsComponent               { *this };
 -     ValueInterfaceComponent valueInterfaceComponent { *this };
 -     StateComponent stateComponent;
 - 
 -     ContentComponent info                    { "Info",
 -                                                "Set the title, role, description and help text properties of the component.",
 -                                                infoComponent };
 -     ContentComponent actions                 { "Actions",
 -                                                "Specify the accessibility actions that the component can perform. When invoked the indicator will flash.",
 -                                                actionsComponent };
 -     ContentComponent valueInterface          { "Value",
 -                                                "Sets the value that this component represents. This can be numeric, ranged or textual and can optionally be read-only.",
 -                                                 valueInterfaceComponent };
 -     ContentComponent state                   { "State",
 -                                                "Modify the AccessibleState properties of the component.",
 -                                                stateComponent };
 - 
 -     AccessibleComponent accessibleComponent { *this };
 - 
 -     //==============================================================================
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CustomWidgetComponent)
 - };
 - 
 - //==============================================================================
 - /**
 -     The top-level component containing an example of custom child component navigation.
 - */
 - class CustomNavigationComponent  : public Component
 - {
 - public:
 -     CustomNavigationComponent()
 -     {
 -         setTitle ("Custom Navigation");
 -         setDescription ("A demo of custom component navigation.");
 -         setFocusContainerType (FocusContainerType::focusContainer);
 - 
 -         addAndMakeVisible (descriptionLabel);
 -         addAndMakeVisible (navigableComponents);
 -     }
 - 
 -     void resized() override
 -     {
 -         Grid grid;
 - 
 -         grid.templateRows = { Grid::TrackInfo (Grid::Fr (1)),
 -                               Grid::TrackInfo (Grid::Fr (2)) };
 - 
 -         grid.templateColumns = { Grid::TrackInfo (Grid::Fr (1)) };
 - 
 -         grid.items = { GridItem (descriptionLabel).withMargin (2),
 -                        GridItem (navigableComponents).withMargin (5) };
 - 
 -         grid.performLayout (getLocalBounds());
 -     }
 - 
 - private:
 -     //==============================================================================
 -     class NavigableComponentsHolder  : public Component
 -     {
 -     public:
 -         NavigableComponentsHolder()
 -         {
 -             setTitle ("Navigable Components");
 -             setDescription ("A container of some navigable components.");
 -             setFocusContainerType (FocusContainerType::focusContainer);
 - 
 -             constexpr int numChildren = 12;
 - 
 -             for (int i = 1; i <= numChildren; ++i)
 -             {
 -                 children.push_back (std::make_unique<NavigableComponent> (i, numChildren, *this));
 -                 addAndMakeVisible (*children.back());
 -             }
 -         }
 - 
 -         void resized() override
 -         {
 -             Grid grid;
 - 
 -             grid.templateRows = { Grid::TrackInfo (Grid::Fr (1)),
 -                                   Grid::TrackInfo (Grid::Fr (1)),
 -                                   Grid::TrackInfo (Grid::Fr (1)),
 -                                   Grid::TrackInfo (Grid::Fr (1)) };
 - 
 -             grid.templateColumns = { Grid::TrackInfo (Grid::Fr (1)), Grid::TrackInfo (Grid::Fr (1)), Grid::TrackInfo (Grid::Fr (1)) };
 - 
 -             for (auto& child : children)
 -                 grid.items.add (GridItem (*child).withMargin (5));
 - 
 -             grid.performLayout (getLocalBounds());
 -         }
 - 
 -         std::unique_ptr<ComponentTraverser> createFocusTraverser() override
 -         {
 -             struct CustomTraverser  : public FocusTraverser
 -             {
 -                 explicit CustomTraverser (NavigableComponentsHolder& owner)
 -                     : navigableComponentsHolder (owner)  {}
 - 
 -                 Component* getDefaultComponent (Component*) override
 -                 {
 -                     for (auto& child : navigableComponentsHolder.children)
 -                         if (child->defaultToggle.getToggleState() && child->focusableToggle.getToggleState())
 -                             return child.get();
 - 
 -                     return nullptr;
 -                 }
 - 
 -                 Component* getNextComponent (Component* current) override
 -                 {
 -                     const auto& comps = navigableComponentsHolder.children;
 - 
 -                     const auto iter = std::find_if (comps.cbegin(), comps.cend(),
 -                                                     [current] (const std::unique_ptr<NavigableComponent>& c) { return c.get() == current; });
 - 
 -                     if (iter != comps.cend() && iter != std::prev (comps.cend()))
 -                         return std::next (iter)->get();
 - 
 -                     return nullptr;
 -                 }
 - 
 -                 Component* getPreviousComponent (Component* current) override
 -                 {
 -                     const auto& comps = navigableComponentsHolder.children;
 - 
 -                     const auto iter = std::find_if (comps.cbegin(), comps.cend(),
 -                                                     [current] (const std::unique_ptr<NavigableComponent>& c) { return c.get() == current; });
 - 
 -                     if (iter != comps.cend() && iter != comps.cbegin())
 -                         return std::prev (iter)->get();
 - 
 -                     return nullptr;
 -                 }
 - 
 -                 std::vector<Component*> getAllComponents (Component*) override
 -                 {
 -                     std::vector<Component*> comps;
 - 
 -                     for (auto& child : navigableComponentsHolder.children)
 -                         if (child->focusableToggle.getToggleState())
 -                             comps.push_back (child.get());
 - 
 -                     return comps;
 -                 }
 - 
 -                 NavigableComponentsHolder& navigableComponentsHolder;
 -             };
 - 
 -             return std::make_unique<CustomTraverser> (*this);
 -         }
 - 
 -     private:
 -         struct NavigableComponent  : public Component
 -         {
 -             NavigableComponent (int index, int total, NavigableComponentsHolder& owner)
 -             {
 -                 const auto textColour = Colours::black.withAlpha (0.8f);
 - 
 -                 titleLabel.setColour (Label::textColourId, textColour);
 -                 orderLabel.setColour (Label::textColourId, textColour);
 - 
 -                 const auto setToggleButtonColours = [textColour] (ToggleButton& b)
 -                 {
 -                     b.setColour (ToggleButton::textColourId, textColour);
 -                     b.setColour (ToggleButton::tickDisabledColourId, textColour);
 -                     b.setColour (ToggleButton::tickColourId, textColour);
 -                 };
 - 
 -                 setToggleButtonColours (focusableToggle);
 -                 setToggleButtonColours (defaultToggle);
 - 
 -                 const auto title = "Component " + String (index);
 -                 setTitle (title);
 -                 titleLabel.setText (title, dontSendNotification);
 -                 focusableToggle.setToggleState (true, dontSendNotification);
 -                 defaultToggle.setToggleState (index == 1, dontSendNotification);
 - 
 -                 for (int i = 1; i <= total; ++i)
 -                     orderBox.addItem (String (i), i);
 - 
 -                 orderBox.setSelectedId (index);
 - 
 -                 orderBox.onChange = [this, &owner] { owner.orderChanged (*this); };
 - 
 -                 focusableToggle.onClick = [this] { repaint(); };
 - 
 -                 defaultToggle.onClick = [this, &owner]
 -                 {
 -                     if (! defaultToggle.getToggleState())
 -                         defaultToggle.setToggleState (true, dontSendNotification);
 -                     else
 -                         owner.defaultChanged (*this);
 -                 };
 - 
 -                 addAndMakeVisible (titleLabel);
 - 
 -                 addAndMakeVisible (focusableToggle);
 -                 addAndMakeVisible (defaultToggle);
 -                 addAndMakeVisible (orderLabel);
 -                 addAndMakeVisible (orderBox);
 - 
 -                 setFocusContainerType (FocusContainerType::focusContainer);
 -             }
 - 
 -             void paint (Graphics& g) override
 -             {
 -                 g.fillAll (backgroundColour.withAlpha (focusableToggle.getToggleState() ? 1.0f : 0.5f));
 -             }
 - 
 -             void resized() override
 -             {
 -                 Grid grid;
 - 
 -                 grid.templateRows = { Grid::TrackInfo (Grid::Fr (2)),
 -                                       Grid::TrackInfo (Grid::Fr (3)),
 -                                       Grid::TrackInfo (Grid::Fr (3)) };
 - 
 -                 grid.templateColumns = { Grid::TrackInfo (Grid::Fr (1)),
 -                                          Grid::TrackInfo (Grid::Fr (1)),
 -                                          Grid::TrackInfo (Grid::Fr (1)),
 -                                          Grid::TrackInfo (Grid::Fr (1)) };
 - 
 -                 grid.items = { GridItem (titleLabel).withMargin (2).withColumn ({ GridItem::Span (4), {} }),
 -                                GridItem (focusableToggle).withMargin (2).withColumn ({ GridItem::Span (2), {} }),
 -                                GridItem (defaultToggle).withMargin (2).withColumn ({ GridItem::Span (2), {} }),
 -                                GridItem (orderLabel).withMargin (2),
 -                                GridItem (orderBox).withMargin (2).withColumn ({ GridItem::Span (3), {} }) };
 - 
 -                 grid.performLayout (getLocalBounds());
 -             }
 - 
 -             Colour backgroundColour = getRandomBrightColour();
 -             Label titleLabel;
 -             ToggleButton focusableToggle { "Focusable" }, defaultToggle { "Default" };
 -             Label orderLabel { {}, "Order" };
 -             ComboBox orderBox;
 -         };
 - 
 -         void orderChanged (const NavigableComponent& changedChild)
 -         {
 -             const auto addressMatches = [&] (const std::unique_ptr<NavigableComponent>& child)
 -             {
 -                 return child.get() == &changedChild;
 -             };
 - 
 -             const auto iter = std::find_if (children.begin(), children.end(), addressMatches);
 - 
 -             if (iter != children.end())
 -                 std::swap (*iter, *std::next (children.begin(), changedChild.orderBox.getSelectedItemIndex()));
 - 
 -             int order = 1;
 - 
 -             for (auto& child : children)
 -                 child->orderBox.setSelectedId (order++);
 - 
 -             if (auto* handler = getAccessibilityHandler())
 -                 handler->notifyAccessibilityEvent (AccessibilityEvent::structureChanged);
 -         }
 - 
 -         void defaultChanged (const NavigableComponent& newDefault)
 -         {
 -             for (auto& child : children)
 -                 if (child->defaultToggle.getToggleState() && child.get() != &newDefault)
 -                     child->defaultToggle.setToggleState (false, dontSendNotification);
 -         }
 - 
 -         std::vector<std::unique_ptr<NavigableComponent>> children;
 - 
 -         //==============================================================================
 -         JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NavigableComponentsHolder)
 -     };
 - 
 -     //==============================================================================
 -     Label descriptionLabel { {}, "This is a demo of how to control the navigation order of components when navigating with an accessibility client.\n\n"
 -                                  "You can set the order of navigation, whether components are focusable and set a default component which will "
 -                                  "receive the focus first." };
 - 
 -     NavigableComponentsHolder navigableComponents;
 - 
 -     //==============================================================================
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CustomNavigationComponent)
 - };
 - 
 - //==============================================================================
 - /**
 -     The top-level component containing an example of how to post system announcements.
 - 
 -     The AccessibilityHandler::postAnnouncement() method will post some text to the native
 -     screen reader application to be read out along with a priority determining how
 -     it should be read out (whether it should interrupt other announcements, etc.).
 - */
 - class AnnouncementsComponent  : public Component
 - {
 - public:
 -     AnnouncementsComponent()
 -     {
 -         addAndMakeVisible (descriptionLabel);
 - 
 -         textEntryBox.setMultiLine (true);
 -         textEntryBox.setReturnKeyStartsNewLine (true);
 -         textEntryBox.setText ("Announcement text.");
 -         addAndMakeVisible (textEntryBox);
 - 
 -         priorityComboBox.addItemList ({ "Priority - Low", "Priority - Medium", "Priority - High" }, 1);
 -         priorityComboBox.setSelectedId (2);
 -         addAndMakeVisible (priorityComboBox);
 - 
 -         announceButton.onClick = [this]
 -         {
 -             auto priority = [this]
 -             {
 -                 switch (priorityComboBox.getSelectedId())
 -                 {
 -                     case 1:   return AccessibilityHandler::AnnouncementPriority::low;
 -                     case 2:   return AccessibilityHandler::AnnouncementPriority::medium;
 -                     case 3:   return AccessibilityHandler::AnnouncementPriority::high;
 -                 }
 - 
 -                 jassertfalse;
 -                 return AccessibilityHandler::AnnouncementPriority::medium;
 -             }();
 - 
 -             AccessibilityHandler::postAnnouncement (textEntryBox.getText(), priority);
 -         };
 - 
 -         addAndMakeVisible (announceButton);
 - 
 -         setTitle ("Announcements");
 -         setHelpText ("Type some text into the box and click the announce button to have it read out.");
 -         setFocusContainerType (FocusContainerType::focusContainer);
 -     }
 - 
 -     void resized() override
 -     {
 -         Grid grid;
 - 
 -         grid.templateRows = { Grid::TrackInfo (Grid::Fr (3)),
 -                               Grid::TrackInfo (Grid::Fr (1)),
 -                               Grid::TrackInfo (Grid::Fr (1)),
 -                               Grid::TrackInfo (Grid::Fr (1)),
 -                               Grid::TrackInfo (Grid::Fr (1)),
 -                               Grid::TrackInfo (Grid::Fr (1)) };
 - 
 -         grid.templateColumns = { Grid::TrackInfo (Grid::Fr (3)),
 -                                  Grid::TrackInfo (Grid::Fr (2)) };
 - 
 -         grid.items = { GridItem (descriptionLabel).withMargin (2).withColumn ({ GridItem::Span (2), {} }),
 -                        GridItem (textEntryBox).withMargin (2).withArea ({ 2 }, { 1 }, { 5 }, { 2 }),
 -                        GridItem (priorityComboBox).withMargin (2).withArea ({ 5 }, { 1 }, { 6 }, { 2 }),
 -                        GridItem (announceButton).withMargin (2).withArea ({ 4 }, { 2 }, { 5 }, { 3 }) };
 - 
 -         grid.performLayout (getLocalBounds());
 -     }
 - 
 - private:
 -     Label descriptionLabel { {}, "This is a demo of posting system announcements that will be read out by an accessibility client.\n\n"
 -                                  "You can enter some text to be read out in the text box below, set a priority for the message and then "
 -                                  "post it using the \"Announce\" button." };
 - 
 -     TextEditor textEntryBox;
 -     ComboBox priorityComboBox;
 -     TextButton announceButton { "Announce" };
 - 
 -     //==============================================================================
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AnnouncementsComponent)
 - };
 - 
 - //==============================================================================
 - /**
 -     The main demo content component.
 - 
 -     This just contains a TabbedComponent with a tab for each of the top-level demos.
 - */
 - class AccessibilityDemo   : public Component
 - {
 - public:
 -     AccessibilityDemo()
 -     {
 -         setTitle ("Accessibility Demo");
 -         setDescription ("A demo of JUCE's accessibility features.");
 -         setFocusContainerType (FocusContainerType::focusContainer);
 - 
 -         tabs.setTitle ("Demo tabs");
 - 
 -         const auto tabColour = getLookAndFeel().findColour (ResizableWindow::backgroundColourId).darker (0.1f);
 - 
 -         tabs.addTab ("JUCE Widgets",      tabColour, &juceWidgetsComponent,      false);
 -         tabs.addTab ("Custom Widget",     tabColour, &customWidgetComponent,     false);
 -         tabs.addTab ("Custom Navigation", tabColour, &customNavigationComponent, false);
 -         tabs.addTab ("Announcements",     tabColour, &announcementsComponent,    false);
 -         addAndMakeVisible (tabs);
 - 
 -         setSize (800, 600);
 -     }
 - 
 -     void paint (Graphics& g) override
 -     {
 -         g.fillAll (getLookAndFeel().findColour (ResizableWindow::backgroundColourId));
 -     }
 - 
 -     void resized() override
 -     {
 -         tabs.setBounds (getLocalBounds());
 -     }
 - 
 - private:
 -     TooltipWindow tooltipWindow { nullptr, 100 };
 - 
 -     TabbedComponent tabs { TabbedButtonBar::Orientation::TabsAtTop };
 - 
 -     JUCEWidgetsComponent juceWidgetsComponent;
 -     CustomWidgetComponent customWidgetComponent;
 -     CustomNavigationComponent customNavigationComponent;
 -     AnnouncementsComponent announcementsComponent;
 - 
 -     //==============================================================================
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AccessibilityDemo)
 - };
 
 
  |