| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library.
 -    Copyright (c) 2020 - Raw Material Software Limited
 - 
 -    JUCE is an open source library subject to commercial or open-source
 -    licensing.
 - 
 -    By using JUCE, you agree to the terms of both the JUCE 6 End-User License
 -    Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
 - 
 -    End User License Agreement: www.juce.com/juce-6-licence
 -    Privacy Policy: www.juce.com/juce-privacy-policy
 - 
 -    Or: You may also use this code under the terms of the GPL v3 (see
 -    www.gnu.org/licenses).
 - 
 -    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
 -    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
 -    DISCLAIMED.
 - 
 -   ==============================================================================
 - */
 - 
 - namespace juce
 - {
 - 
 - namespace LookAndFeelHelpers
 - {
 -     static Colour createBaseColour (Colour buttonColour,
 -                                     bool hasKeyboardFocus,
 -                                     bool shouldDrawButtonAsHighlighted,
 -                                     bool shouldDrawButtonAsDown) noexcept
 -     {
 -         const float sat = hasKeyboardFocus ? 1.3f : 0.9f;
 -         const Colour baseColour (buttonColour.withMultipliedSaturation (sat));
 - 
 -         if (shouldDrawButtonAsDown)        return baseColour.contrasting (0.2f);
 -         if (shouldDrawButtonAsHighlighted) return baseColour.contrasting (0.1f);
 - 
 -         return baseColour;
 -     }
 - 
 -     static TextLayout layoutTooltipText (const String& text, Colour colour) noexcept
 -     {
 -         const float tooltipFontSize = 13.0f;
 -         const int maxToolTipWidth = 400;
 - 
 -         AttributedString s;
 -         s.setJustification (Justification::centred);
 -         s.append (text, Font (tooltipFontSize, Font::bold), colour);
 - 
 -         TextLayout tl;
 -         tl.createLayoutWithBalancedLineLengths (s, (float) maxToolTipWidth);
 -         return tl;
 -     }
 - }
 - 
 - //==============================================================================
 - LookAndFeel_V2::LookAndFeel_V2()
 - {
 -     // initialise the standard set of colours..
 -     const uint32 textButtonColour      = 0xffbbbbff;
 -     const uint32 textHighlightColour   = 0x401111ee;
 -     const uint32 standardOutlineColour = 0xb2808080;
 - 
 -     static const uint32 standardColours[] =
 -     {
 -         TextButton::buttonColourId,                 textButtonColour,
 -         TextButton::buttonOnColourId,               0xff4444ff,
 -         TextButton::textColourOnId,                 0xff000000,
 -         TextButton::textColourOffId,                0xff000000,
 - 
 -         ToggleButton::textColourId,                 0xff000000,
 -         ToggleButton::tickColourId,                 0xff000000,
 -         ToggleButton::tickDisabledColourId,         0xff808080,
 - 
 -         TextEditor::backgroundColourId,             0xffffffff,
 -         TextEditor::textColourId,                   0xff000000,
 -         TextEditor::highlightColourId,              textHighlightColour,
 -         TextEditor::highlightedTextColourId,        0xff000000,
 -         TextEditor::outlineColourId,                0x00000000,
 -         TextEditor::focusedOutlineColourId,         textButtonColour,
 -         TextEditor::shadowColourId,                 0x38000000,
 - 
 -         CaretComponent::caretColourId,              0xff000000,
 - 
 -         Label::backgroundColourId,                  0x00000000,
 -         Label::textColourId,                        0xff000000,
 -         Label::outlineColourId,                     0x00000000,
 - 
 -         ScrollBar::backgroundColourId,              0x00000000,
 -         ScrollBar::thumbColourId,                   0xffffffff,
 - 
 -         TreeView::linesColourId,                    0x4c000000,
 -         TreeView::backgroundColourId,               0x00000000,
 -         TreeView::dragAndDropIndicatorColourId,     0x80ff0000,
 -         TreeView::selectedItemBackgroundColourId,   0x00000000,
 -         TreeView::oddItemsColourId,                 0x00000000,
 -         TreeView::evenItemsColourId,                0x00000000,
 - 
 -         PopupMenu::backgroundColourId,              0xffffffff,
 -         PopupMenu::textColourId,                    0xff000000,
 -         PopupMenu::headerTextColourId,              0xff000000,
 -         PopupMenu::highlightedTextColourId,         0xffffffff,
 -         PopupMenu::highlightedBackgroundColourId,   0x991111aa,
 - 
 -         ComboBox::buttonColourId,                   0xffbbbbff,
 -         ComboBox::outlineColourId,                  standardOutlineColour,
 -         ComboBox::textColourId,                     0xff000000,
 -         ComboBox::backgroundColourId,               0xffffffff,
 -         ComboBox::arrowColourId,                    0x99000000,
 -         ComboBox::focusedOutlineColourId,           0xffbbbbff,
 - 
 -         PropertyComponent::backgroundColourId,      0x66ffffff,
 -         PropertyComponent::labelTextColourId,       0xff000000,
 - 
 -         TextPropertyComponent::backgroundColourId,  0xffffffff,
 -         TextPropertyComponent::textColourId,        0xff000000,
 -         TextPropertyComponent::outlineColourId,     standardOutlineColour,
 - 
 -         BooleanPropertyComponent::backgroundColourId, 0xffffffff,
 -         BooleanPropertyComponent::outlineColourId,  standardOutlineColour,
 - 
 -         ListBox::backgroundColourId,                0xffffffff,
 -         ListBox::outlineColourId,                   standardOutlineColour,
 -         ListBox::textColourId,                      0xff000000,
 - 
 -         Slider::backgroundColourId,                 0x00000000,
 -         Slider::thumbColourId,                      textButtonColour,
 -         Slider::trackColourId,                      0x7fffffff,
 -         Slider::rotarySliderFillColourId,           0x7f0000ff,
 -         Slider::rotarySliderOutlineColourId,        0x66000000,
 -         Slider::textBoxTextColourId,                0xff000000,
 -         Slider::textBoxBackgroundColourId,          0xffffffff,
 -         Slider::textBoxHighlightColourId,           textHighlightColour,
 -         Slider::textBoxOutlineColourId,             standardOutlineColour,
 - 
 -         ResizableWindow::backgroundColourId,        0xff777777,
 -         //DocumentWindow::textColourId,               0xff000000, // (this is deliberately not set)
 - 
 -         AlertWindow::backgroundColourId,            0xffededed,
 -         AlertWindow::textColourId,                  0xff000000,
 -         AlertWindow::outlineColourId,               0xff666666,
 - 
 -         ProgressBar::backgroundColourId,            0xffeeeeee,
 -         ProgressBar::foregroundColourId,            0xffaaaaee,
 - 
 -         TooltipWindow::backgroundColourId,          0xffeeeebb,
 -         TooltipWindow::textColourId,                0xff000000,
 -         TooltipWindow::outlineColourId,             0x4c000000,
 - 
 -         TabbedComponent::backgroundColourId,        0x00000000,
 -         TabbedComponent::outlineColourId,           0xff777777,
 -         TabbedButtonBar::tabOutlineColourId,        0x80000000,
 -         TabbedButtonBar::frontOutlineColourId,      0x90000000,
 - 
 -         Toolbar::backgroundColourId,                0xfff6f8f9,
 -         Toolbar::separatorColourId,                 0x4c000000,
 -         Toolbar::buttonMouseOverBackgroundColourId, 0x4c0000ff,
 -         Toolbar::buttonMouseDownBackgroundColourId, 0x800000ff,
 -         Toolbar::labelTextColourId,                 0xff000000,
 -         Toolbar::editingModeOutlineColourId,        0xffff0000,
 - 
 -         DrawableButton::textColourId,               0xff000000,
 -         DrawableButton::textColourOnId,             0xff000000,
 -         DrawableButton::backgroundColourId,         0x00000000,
 -         DrawableButton::backgroundOnColourId,       0xaabbbbff,
 - 
 -         HyperlinkButton::textColourId,              0xcc1111ee,
 - 
 -         GroupComponent::outlineColourId,            0x66000000,
 -         GroupComponent::textColourId,               0xff000000,
 - 
 -         BubbleComponent::backgroundColourId,        0xeeeeeebb,
 -         BubbleComponent::outlineColourId,           0x77000000,
 - 
 -         TableHeaderComponent::textColourId,         0xff000000,
 -         TableHeaderComponent::backgroundColourId,   0xffe8ebf9,
 -         TableHeaderComponent::outlineColourId,      0x33000000,
 -         TableHeaderComponent::highlightColourId,    0x8899aadd,
 - 
 -         DirectoryContentsDisplayComponent::highlightColourId,              textHighlightColour,
 -         DirectoryContentsDisplayComponent::textColourId,                   0xff000000,
 -         DirectoryContentsDisplayComponent::highlightedTextColourId,        0xff000000,
 - 
 -         0x1000440, /*LassoComponent::lassoFillColourId*/        0x66dddddd,
 -         0x1000441, /*LassoComponent::lassoOutlineColourId*/     0x99111111,
 - 
 -         0x1005000, /*MidiKeyboardComponent::whiteNoteColourId*/               0xffffffff,
 -         0x1005001, /*MidiKeyboardComponent::blackNoteColourId*/               0xff000000,
 -         0x1005002, /*MidiKeyboardComponent::keySeparatorLineColourId*/        0x66000000,
 -         0x1005003, /*MidiKeyboardComponent::mouseOverKeyOverlayColourId*/     0x80ffff00,
 -         0x1005004, /*MidiKeyboardComponent::keyDownOverlayColourId*/          0xffb6b600,
 -         0x1005005, /*MidiKeyboardComponent::textLabelColourId*/               0xff000000,
 -         0x1005006, /*MidiKeyboardComponent::upDownButtonBackgroundColourId*/  0xffd3d3d3,
 -         0x1005007, /*MidiKeyboardComponent::upDownButtonArrowColourId*/       0xff000000,
 -         0x1005008, /*MidiKeyboardComponent::shadowColourId*/                  0x4c000000,
 - 
 -         0x1004500, /*CodeEditorComponent::backgroundColourId*/                0xffffffff,
 -         0x1004502, /*CodeEditorComponent::highlightColourId*/                 textHighlightColour,
 -         0x1004503, /*CodeEditorComponent::defaultTextColourId*/               0xff000000,
 -         0x1004504, /*CodeEditorComponent::lineNumberBackgroundId*/            0x44999999,
 -         0x1004505, /*CodeEditorComponent::lineNumberTextId*/                  0x44000000,
 - 
 -         0x1007000, /*ColourSelector::backgroundColourId*/                     0xffe5e5e5,
 -         0x1007001, /*ColourSelector::labelTextColourId*/                      0xff000000,
 - 
 -         0x100ad00, /*KeyMappingEditorComponent::backgroundColourId*/          0x00000000,
 -         0x100ad01, /*KeyMappingEditorComponent::textColourId*/                0xff000000,
 - 
 -         FileSearchPathListComponent::backgroundColourId,        0xffffffff,
 - 
 -         FileChooserDialogBox::titleTextColourId,                0xff000000,
 - 
 -         SidePanel::backgroundColour,                            0xffffffff,
 -         SidePanel::titleTextColour,                             0xff000000,
 -         SidePanel::shadowBaseColour,                            0xff000000,
 -         SidePanel::dismissButtonNormalColour,                   textButtonColour,
 -         SidePanel::dismissButtonOverColour,                     textButtonColour,
 -         SidePanel::dismissButtonDownColour,                     0xff4444ff,
 - 
 -         FileBrowserComponent::currentPathBoxBackgroundColourId,    0xffffffff,
 -         FileBrowserComponent::currentPathBoxTextColourId,          0xff000000,
 -         FileBrowserComponent::currentPathBoxArrowColourId,         0x99000000,
 -         FileBrowserComponent::filenameBoxBackgroundColourId,       0xffffffff,
 -         FileBrowserComponent::filenameBoxTextColourId,             0xff000000,
 -     };
 - 
 -     for (int i = 0; i < numElementsInArray (standardColours); i += 2)
 -         setColour ((int) standardColours [i], Colour ((uint32) standardColours [i + 1]));
 - }
 - 
 - LookAndFeel_V2::~LookAndFeel_V2()  {}
 - 
 - //==============================================================================
 - void LookAndFeel_V2::drawButtonBackground (Graphics& g,
 -                                            Button& button,
 -                                            const Colour& backgroundColour,
 -                                            bool shouldDrawButtonAsHighlighted,
 -                                            bool shouldDrawButtonAsDown)
 - {
 -     const int width = button.getWidth();
 -     const int height = button.getHeight();
 - 
 -     const float outlineThickness = button.isEnabled() ? ((shouldDrawButtonAsDown || shouldDrawButtonAsHighlighted) ? 1.2f : 0.7f) : 0.4f;
 -     const float halfThickness = outlineThickness * 0.5f;
 - 
 -     const float indentL = button.isConnectedOnLeft()   ? 0.1f : halfThickness;
 -     const float indentR = button.isConnectedOnRight()  ? 0.1f : halfThickness;
 -     const float indentT = button.isConnectedOnTop()    ? 0.1f : halfThickness;
 -     const float indentB = button.isConnectedOnBottom() ? 0.1f : halfThickness;
 - 
 -     const Colour baseColour (LookAndFeelHelpers::createBaseColour (backgroundColour,
 -                                                                    button.hasKeyboardFocus (true),
 -                                                                    shouldDrawButtonAsHighlighted,
 -                                                                    shouldDrawButtonAsDown)
 -                                .withMultipliedAlpha (button.isEnabled() ? 1.0f : 0.5f));
 - 
 -     drawGlassLozenge (g,
 -                       indentL,
 -                       indentT,
 -                       (float) width - indentL - indentR,
 -                       (float) height - indentT - indentB,
 -                       baseColour, outlineThickness, -1.0f,
 -                       button.isConnectedOnLeft(),
 -                       button.isConnectedOnRight(),
 -                       button.isConnectedOnTop(),
 -                       button.isConnectedOnBottom());
 - }
 - 
 - Font LookAndFeel_V2::getTextButtonFont (TextButton&, int buttonHeight)
 - {
 -     return Font (jmin (15.0f, (float) buttonHeight * 0.6f));
 - }
 - 
 - int LookAndFeel_V2::getTextButtonWidthToFitText (TextButton& b, int buttonHeight)
 - {
 -     return getTextButtonFont (b, buttonHeight).getStringWidth (b.getButtonText()) + buttonHeight;
 - }
 - 
 - void LookAndFeel_V2::drawButtonText (Graphics& g, TextButton& button,
 -                                      bool /*shouldDrawButtonAsHighlighted*/, bool /*shouldDrawButtonAsDown*/)
 - {
 -     Font font (getTextButtonFont (button, button.getHeight()));
 -     g.setFont (font);
 -     g.setColour (button.findColour (button.getToggleState() ? TextButton::textColourOnId
 -                                                             : TextButton::textColourOffId)
 -                        .withMultipliedAlpha (button.isEnabled() ? 1.0f : 0.5f));
 - 
 -     const int yIndent = jmin (4, button.proportionOfHeight (0.3f));
 -     const int cornerSize = jmin (button.getHeight(), button.getWidth()) / 2;
 - 
 -     const int fontHeight = roundToInt (font.getHeight() * 0.6f);
 -     const int leftIndent  = jmin (fontHeight, 2 + cornerSize / (button.isConnectedOnLeft() ? 4 : 2));
 -     const int rightIndent = jmin (fontHeight, 2 + cornerSize / (button.isConnectedOnRight() ? 4 : 2));
 -     const int textWidth = button.getWidth() - leftIndent - rightIndent;
 - 
 -     if (textWidth > 0)
 -         g.drawFittedText (button.getButtonText(),
 -                           leftIndent, yIndent, textWidth, button.getHeight() - yIndent * 2,
 -                           Justification::centred, 2);
 - }
 - 
 - void LookAndFeel_V2::drawTickBox (Graphics& g, Component& component,
 -                                   float x, float y, float w, float h,
 -                                   const bool ticked,
 -                                   const bool isEnabled,
 -                                   const bool shouldDrawButtonAsHighlighted,
 -                                   const bool shouldDrawButtonAsDown)
 - {
 -     const float boxSize = w * 0.7f;
 - 
 -     drawGlassSphere (g, x, y + (h - boxSize) * 0.5f, boxSize,
 -                      LookAndFeelHelpers::createBaseColour (component.findColour (TextButton::buttonColourId)
 -                                                                     .withMultipliedAlpha (isEnabled ? 1.0f : 0.5f),
 -                                                            true, shouldDrawButtonAsHighlighted, shouldDrawButtonAsDown),
 -                      isEnabled ? ((shouldDrawButtonAsDown || shouldDrawButtonAsHighlighted) ? 1.1f : 0.5f) : 0.3f);
 - 
 -     if (ticked)
 -     {
 -         Path tick;
 -         tick.startNewSubPath (1.5f, 3.0f);
 -         tick.lineTo (3.0f, 6.0f);
 -         tick.lineTo (6.0f, 0.0f);
 - 
 -         g.setColour (component.findColour (isEnabled ? ToggleButton::tickColourId
 -                                                      : ToggleButton::tickDisabledColourId));
 - 
 -         const AffineTransform trans (AffineTransform::scale (w / 9.0f, h / 9.0f)
 -                                                      .translated (x, y));
 - 
 -         g.strokePath (tick, PathStrokeType (2.5f), trans);
 -     }
 - }
 - 
 - void LookAndFeel_V2::drawToggleButton (Graphics& g, ToggleButton& button,
 -                                        bool shouldDrawButtonAsHighlighted, bool shouldDrawButtonAsDown)
 - {
 -     if (button.hasKeyboardFocus (true))
 -     {
 -         g.setColour (button.findColour (TextEditor::focusedOutlineColourId));
 -         g.drawRect (0, 0, button.getWidth(), button.getHeight());
 -     }
 - 
 -     float fontSize = jmin (15.0f, (float) button.getHeight() * 0.75f);
 -     const float tickWidth = fontSize * 1.1f;
 - 
 -     drawTickBox (g, button, 4.0f, ((float) button.getHeight() - tickWidth) * 0.5f,
 -                  tickWidth, tickWidth,
 -                  button.getToggleState(),
 -                  button.isEnabled(),
 -                  shouldDrawButtonAsHighlighted,
 -                  shouldDrawButtonAsDown);
 - 
 -     g.setColour (button.findColour (ToggleButton::textColourId));
 -     g.setFont (fontSize);
 - 
 -     if (! button.isEnabled())
 -         g.setOpacity (0.5f);
 - 
 -     g.drawFittedText (button.getButtonText(),
 -                       button.getLocalBounds().withTrimmedLeft (roundToInt (tickWidth) + 5)
 -                                              .withTrimmedRight (2),
 -                       Justification::centredLeft, 10);
 - }
 - 
 - void LookAndFeel_V2::changeToggleButtonWidthToFitText (ToggleButton& button)
 - {
 -     auto fontSize = jmin (15.0f, (float) button.getHeight() * 0.75f);
 -     auto tickWidth = fontSize * 1.1f;
 - 
 -     Font font (fontSize);
 - 
 -     button.setSize (font.getStringWidth (button.getButtonText()) + roundToInt (tickWidth) + 9,
 -                     button.getHeight());
 - }
 - 
 - void LookAndFeel_V2::drawDrawableButton (Graphics& g, DrawableButton& button,
 -                                          bool /*shouldDrawButtonAsHighlighted*/, bool /*shouldDrawButtonAsDown*/)
 - {
 -     bool toggleState = button.getToggleState();
 - 
 -     g.fillAll (button.findColour (toggleState ? DrawableButton::backgroundOnColourId
 -                                               : DrawableButton::backgroundColourId));
 - 
 -     const int textH = (button.getStyle() == DrawableButton::ImageAboveTextLabel)
 -                         ? jmin (16, button.proportionOfHeight (0.25f))
 -                         : 0;
 - 
 -     if (textH > 0)
 -     {
 -         g.setFont ((float) textH);
 - 
 -         g.setColour (button.findColour (toggleState ? DrawableButton::textColourOnId
 -                                                     : DrawableButton::textColourId)
 -                         .withMultipliedAlpha (button.isEnabled() ? 1.0f : 0.4f));
 - 
 -         g.drawFittedText (button.getButtonText(),
 -                           2, button.getHeight() - textH - 1,
 -                           button.getWidth() - 4, textH,
 -                           Justification::centred, 1);
 -     }
 - }
 - 
 - //==============================================================================
 - AlertWindow* LookAndFeel_V2::createAlertWindow (const String& title, const String& message,
 -                                                 const String& button1, const String& button2, const String& button3,
 -                                                 AlertWindow::AlertIconType iconType,
 -                                                 int numButtons, Component* associatedComponent)
 - {
 -     AlertWindow* aw = new AlertWindow (title, message, iconType, associatedComponent);
 - 
 -     if (numButtons == 1)
 -     {
 -         aw->addButton (button1, 0,
 -                        KeyPress (KeyPress::escapeKey),
 -                        KeyPress (KeyPress::returnKey));
 -     }
 -     else
 -     {
 -         const KeyPress button1ShortCut ((int) CharacterFunctions::toLowerCase (button1[0]), 0, 0);
 -         KeyPress button2ShortCut ((int) CharacterFunctions::toLowerCase (button2[0]), 0, 0);
 -         if (button1ShortCut == button2ShortCut)
 -             button2ShortCut = KeyPress();
 - 
 -         if (numButtons == 2)
 -         {
 -             aw->addButton (button1, 1, KeyPress (KeyPress::returnKey), button1ShortCut);
 -             aw->addButton (button2, 0, KeyPress (KeyPress::escapeKey), button2ShortCut);
 -         }
 -         else if (numButtons == 3)
 -         {
 -             aw->addButton (button1, 1, button1ShortCut);
 -             aw->addButton (button2, 2, button2ShortCut);
 -             aw->addButton (button3, 0, KeyPress (KeyPress::escapeKey));
 -         }
 -     }
 - 
 -     return aw;
 - }
 - 
 - void LookAndFeel_V2::drawAlertBox (Graphics& g, AlertWindow& alert,
 -                                    const Rectangle<int>& textArea, TextLayout& textLayout)
 - {
 -     g.fillAll (alert.findColour (AlertWindow::backgroundColourId));
 - 
 -     int iconSpaceUsed = 0;
 - 
 -     const int iconWidth = 80;
 -     int iconSize = jmin (iconWidth + 50, alert.getHeight() + 20);
 - 
 -     if (alert.containsAnyExtraComponents() || alert.getNumButtons() > 2)
 -         iconSize = jmin (iconSize, textArea.getHeight() + 50);
 - 
 -     const Rectangle<int> iconRect (iconSize / -10, iconSize / -10,
 -                                    iconSize, iconSize);
 - 
 -     if (alert.getAlertType() != AlertWindow::NoIcon)
 -     {
 -         Path icon;
 -         uint32 colour;
 -         char character;
 - 
 -         if (alert.getAlertType() == AlertWindow::WarningIcon)
 -         {
 -             colour = 0x55ff5555;
 -             character = '!';
 - 
 -             icon.addTriangle ((float) iconRect.getX() + (float) iconRect.getWidth() * 0.5f, (float) iconRect.getY(),
 -                               (float) iconRect.getRight(), (float) iconRect.getBottom(),
 -                               (float) iconRect.getX(), (float) iconRect.getBottom());
 - 
 -             icon = icon.createPathWithRoundedCorners (5.0f);
 -         }
 -         else
 -         {
 -             colour    = alert.getAlertType() == AlertWindow::InfoIcon ? (uint32) 0x605555ff : (uint32) 0x40b69900;
 -             character = alert.getAlertType() == AlertWindow::InfoIcon ? 'i' : '?';
 - 
 -             icon.addEllipse (iconRect.toFloat());
 -         }
 - 
 -         GlyphArrangement ga;
 -         ga.addFittedText (Font ((float) iconRect.getHeight() * 0.9f, Font::bold),
 -                           String::charToString ((juce_wchar) (uint8) character),
 -                           (float) iconRect.getX(), (float) iconRect.getY(),
 -                           (float) iconRect.getWidth(), (float) iconRect.getHeight(),
 -                           Justification::centred, false);
 -         ga.createPath (icon);
 - 
 -         icon.setUsingNonZeroWinding (false);
 -         g.setColour (Colour (colour));
 -         g.fillPath (icon);
 - 
 -         iconSpaceUsed = iconWidth;
 -     }
 - 
 -     g.setColour (alert.findColour (AlertWindow::textColourId));
 - 
 -     textLayout.draw (g, Rectangle<int> (textArea.getX() + iconSpaceUsed,
 -                                         textArea.getY(),
 -                                         textArea.getWidth() - iconSpaceUsed,
 -                                         textArea.getHeight()).toFloat());
 - 
 -     g.setColour (alert.findColour (AlertWindow::outlineColourId));
 -     g.drawRect (0, 0, alert.getWidth(), alert.getHeight());
 - }
 - 
 - int LookAndFeel_V2::getAlertBoxWindowFlags()
 - {
 -     return ComponentPeer::windowAppearsOnTaskbar
 -             | ComponentPeer::windowHasDropShadow;
 - }
 - 
 - Array<int> LookAndFeel_V2::getWidthsForTextButtons (AlertWindow&, const Array<TextButton*>& buttons)
 - {
 -     const int n = buttons.size();
 -     Array<int> buttonWidths;
 - 
 -     const int buttonHeight = getAlertWindowButtonHeight();
 - 
 -     for (int i = 0; i < n; ++i)
 -         buttonWidths.add (getTextButtonWidthToFitText (*buttons.getReference (i), buttonHeight));
 - 
 -     return buttonWidths;
 - }
 - 
 - int LookAndFeel_V2::getAlertWindowButtonHeight()
 - {
 -     return 28;
 - }
 - 
 - Font LookAndFeel_V2::getAlertWindowTitleFont()
 - {
 -     Font messageFont = getAlertWindowMessageFont();
 -     return messageFont.withHeight (messageFont.getHeight() * 1.1f).boldened();
 - }
 - 
 - Font LookAndFeel_V2::getAlertWindowMessageFont()
 - {
 -     return Font (15.0f);
 - }
 - 
 - Font LookAndFeel_V2::getAlertWindowFont()
 - {
 -     return Font (12.0f);
 - }
 - 
 - //==============================================================================
 - void LookAndFeel_V2::drawProgressBar (Graphics& g, ProgressBar& progressBar,
 -                                       int width, int height,
 -                                       double progress, const String& textToShow)
 - {
 -     const Colour background (progressBar.findColour (ProgressBar::backgroundColourId));
 -     const Colour foreground (progressBar.findColour (ProgressBar::foregroundColourId));
 - 
 -     g.fillAll (background);
 - 
 -     if (progress >= 0.0f && progress < 1.0f)
 -     {
 -         drawGlassLozenge (g, 1.0f, 1.0f,
 -                           (float) jlimit (0.0, width - 2.0, progress * (width - 2.0)),
 -                           (float) (height - 2),
 -                           foreground,
 -                           0.5f, 0.0f,
 -                           true, true, true, true);
 -     }
 -     else
 -     {
 -         // spinning bar..
 -         g.setColour (foreground);
 - 
 -         const int stripeWidth = height * 2;
 -         const int position = (int) (Time::getMillisecondCounter() / 15) % stripeWidth;
 - 
 -         Path p;
 - 
 -         for (float x = (float) (- position); x < (float) (width + stripeWidth); x += (float) stripeWidth)
 -             p.addQuadrilateral (x, 0.0f,
 -                                 x + (float) stripeWidth * 0.5f, 0.0f,
 -                                 x, (float) height,
 -                                 x - (float) stripeWidth * 0.5f, (float) height);
 - 
 -         Image im (Image::ARGB, width, height, true);
 - 
 -         {
 -             Graphics g2 (im);
 -             drawGlassLozenge (g2, 1.0f, 1.0f,
 -                               (float) (width - 2),
 -                               (float) (height - 2),
 -                               foreground,
 -                               0.5f, 0.0f,
 -                               true, true, true, true);
 -         }
 - 
 -         g.setTiledImageFill (im, 0, 0, 0.85f);
 -         g.fillPath (p);
 -     }
 - 
 -     if (textToShow.isNotEmpty())
 -     {
 -         g.setColour (Colour::contrasting (background, foreground));
 -         g.setFont ((float) height * 0.6f);
 - 
 -         g.drawText (textToShow, 0, 0, width, height, Justification::centred, false);
 -     }
 - }
 - 
 - void LookAndFeel_V2::drawSpinningWaitAnimation (Graphics& g, const Colour& colour, int x, int y, int w, int h)
 - {
 -     const float radius = (float) jmin (w, h) * 0.4f;
 -     const float thickness = radius * 0.15f;
 -     Path p;
 -     p.addRoundedRectangle (radius * 0.4f, thickness * -0.5f,
 -                            radius * 0.6f, thickness,
 -                            thickness * 0.5f);
 - 
 -     const float cx = (float) x + (float) w * 0.5f;
 -     const float cy = (float) y + (float) h * 0.5f;
 - 
 -     const uint32 animationIndex = (Time::getMillisecondCounter() / (1000 / 10)) % 12;
 - 
 -     for (uint32 i = 0; i < 12; ++i)
 -     {
 -         const uint32 n = (i + 12 - animationIndex) % 12;
 - 
 -         g.setColour (colour.withMultipliedAlpha ((float) (n + 1) / 12.0f));
 -         g.fillPath (p, AffineTransform::rotation ((float) i * (MathConstants<float>::pi / 6.0f))
 -                                        .translated (cx, cy));
 -     }
 - }
 - 
 - bool LookAndFeel_V2::isProgressBarOpaque (ProgressBar& progressBar)
 - {
 -     return progressBar.findColour (ProgressBar::backgroundColourId).isOpaque();
 - }
 - 
 - bool LookAndFeel_V2::areScrollbarButtonsVisible()
 - {
 -     return true;
 - }
 - 
 - void LookAndFeel_V2::drawScrollbarButton (Graphics& g, ScrollBar& scrollbar,
 -                                           int width, int height, int buttonDirection,
 -                                           bool /*isScrollbarVertical*/,
 -                                           bool /*shouldDrawButtonAsHighlighted*/,
 -                                           bool shouldDrawButtonAsDown)
 - {
 -     Path p;
 - 
 -     const auto w = (float) width;
 -     const auto h = (float) height;
 - 
 -     if (buttonDirection == 0)
 -         p.addTriangle (w * 0.5f, h * 0.2f,
 -                        w * 0.1f, h * 0.7f,
 -                        w * 0.9f, h * 0.7f);
 -     else if (buttonDirection == 1)
 -         p.addTriangle (w * 0.8f, h * 0.5f,
 -                        w * 0.3f, h * 0.1f,
 -                        w * 0.3f, h * 0.9f);
 -     else if (buttonDirection == 2)
 -         p.addTriangle (w * 0.5f, h * 0.8f,
 -                        w * 0.1f, h * 0.3f,
 -                        w * 0.9f, h * 0.3f);
 -     else if (buttonDirection == 3)
 -         p.addTriangle (w * 0.2f, h * 0.5f,
 -                        w * 0.7f, h * 0.1f,
 -                        w * 0.7f, h * 0.9f);
 - 
 -     if (shouldDrawButtonAsDown)
 -         g.setColour (scrollbar.findColour (ScrollBar::thumbColourId).contrasting (0.2f));
 -     else
 -         g.setColour (scrollbar.findColour (ScrollBar::thumbColourId));
 - 
 -     g.fillPath (p);
 - 
 -     g.setColour (Colour (0x80000000));
 -     g.strokePath (p, PathStrokeType (0.5f));
 - }
 - 
 - void LookAndFeel_V2::drawScrollbar (Graphics& g,
 -                                  ScrollBar& scrollbar,
 -                                  int x, int y,
 -                                  int width, int height,
 -                                  bool isScrollbarVertical,
 -                                  int thumbStartPosition,
 -                                  int thumbSize,
 -                                  bool /*isMouseOver*/,
 -                                  bool /*isMouseDown*/)
 - {
 -     g.fillAll (scrollbar.findColour (ScrollBar::backgroundColourId));
 - 
 -     Path slotPath, thumbPath;
 - 
 -     const float slotIndent = jmin (width, height) > 15 ? 1.0f : 0.0f;
 -     const float slotIndentx2 = slotIndent * 2.0f;
 -     const float thumbIndent = slotIndent + 1.0f;
 -     const float thumbIndentx2 = thumbIndent * 2.0f;
 - 
 -     float gx1 = 0.0f, gy1 = 0.0f, gx2 = 0.0f, gy2 = 0.0f;
 - 
 -     if (isScrollbarVertical)
 -     {
 -         slotPath.addRoundedRectangle ((float) x + slotIndent,
 -                                       (float) y + slotIndent,
 -                                       (float) width - slotIndentx2,
 -                                       (float) height - slotIndentx2,
 -                                       ((float) width - slotIndentx2) * 0.5f);
 - 
 -         if (thumbSize > 0)
 -             thumbPath.addRoundedRectangle ((float) x + thumbIndent,
 -                                            (float) thumbStartPosition + thumbIndent,
 -                                            (float) width - thumbIndentx2,
 -                                            (float) thumbSize - thumbIndentx2,
 -                                            ((float) width - thumbIndentx2) * 0.5f);
 -         gx1 = (float) x;
 -         gx2 = (float) x + (float) width * 0.7f;
 -     }
 -     else
 -     {
 -         slotPath.addRoundedRectangle ((float) x + slotIndent,
 -                                       (float) y + slotIndent,
 -                                       (float) width - slotIndentx2,
 -                                       (float) height - slotIndentx2,
 -                                       ((float) height - slotIndentx2) * 0.5f);
 - 
 -         if (thumbSize > 0)
 -             thumbPath.addRoundedRectangle ((float) thumbStartPosition + thumbIndent,
 -                                            (float) y + thumbIndent,
 -                                            (float) thumbSize - thumbIndentx2,
 -                                            (float) height - thumbIndentx2,
 -                                            ((float) height - thumbIndentx2) * 0.5f);
 -         gy1 = (float) y;
 -         gy2 = (float) y + (float) height * 0.7f;
 -     }
 - 
 -     const Colour thumbColour (scrollbar.findColour (ScrollBar::thumbColourId));
 -     Colour trackColour1, trackColour2;
 - 
 -     if (scrollbar.isColourSpecified (ScrollBar::trackColourId)
 -          || isColourSpecified (ScrollBar::trackColourId))
 -     {
 -         trackColour1 = trackColour2 = scrollbar.findColour (ScrollBar::trackColourId);
 -     }
 -     else
 -     {
 -         trackColour1 = thumbColour.overlaidWith (Colour (0x44000000));
 -         trackColour2 = thumbColour.overlaidWith (Colour (0x19000000));
 -     }
 - 
 -     g.setGradientFill (ColourGradient (trackColour1, gx1, gy1,
 -                                        trackColour2, gx2, gy2, false));
 -     g.fillPath (slotPath);
 - 
 -     if (isScrollbarVertical)
 -     {
 -         gx1 = (float) x + (float) width * 0.6f;
 -         gx2 = (float) x + (float) width;
 -     }
 -     else
 -     {
 -         gy1 = (float) y + (float) height * 0.6f;
 -         gy2 = (float) y + (float) height;
 -     }
 - 
 -     g.setGradientFill (ColourGradient (Colours::transparentBlack,gx1, gy1,
 -                        Colour (0x19000000), gx2, gy2, false));
 -     g.fillPath (slotPath);
 - 
 -     g.setColour (thumbColour);
 -     g.fillPath (thumbPath);
 - 
 -     g.setGradientFill (ColourGradient (Colour (0x10000000), gx1, gy1,
 -                        Colours::transparentBlack, gx2, gy2, false));
 - 
 -     {
 -         Graphics::ScopedSaveState ss (g);
 - 
 -         if (isScrollbarVertical)
 -             g.reduceClipRegion (x + width / 2, y, width, height);
 -         else
 -             g.reduceClipRegion (x, y + height / 2, width, height);
 - 
 -         g.fillPath (thumbPath);
 -     }
 - 
 -     g.setColour (Colour (0x4c000000));
 -     g.strokePath (thumbPath, PathStrokeType (0.4f));
 - }
 - 
 - ImageEffectFilter* LookAndFeel_V2::getScrollbarEffect()
 - {
 -     return nullptr;
 - }
 - 
 - int LookAndFeel_V2::getMinimumScrollbarThumbSize (ScrollBar& scrollbar)
 - {
 -     return jmin (scrollbar.getWidth(), scrollbar.getHeight()) * 2;
 - }
 - 
 - int LookAndFeel_V2::getDefaultScrollbarWidth()
 - {
 -     return 18;
 - }
 - 
 - int LookAndFeel_V2::getScrollbarButtonSize (ScrollBar& scrollbar)
 - {
 -     return 2 + (scrollbar.isVertical() ? scrollbar.getWidth()
 -                                        : scrollbar.getHeight());
 - }
 - 
 - //==============================================================================
 - void LookAndFeel_V2::drawTreeviewPlusMinusBox (Graphics& g, const Rectangle<float>& area,
 -                                                Colour /*backgroundColour*/, bool isOpen, bool /*isMouseOver*/)
 - {
 -     auto boxSize = roundToInt (jmin (16.0f, area.getWidth(), area.getHeight()) * 0.7f) | 1;
 - 
 -     auto x = ((int) area.getWidth()  - boxSize) / 2 + (int) area.getX();
 -     auto y = ((int) area.getHeight() - boxSize) / 2 + (int) area.getY();
 - 
 -     Rectangle<float> boxArea ((float) x, (float) y, (float) boxSize, (float) boxSize);
 - 
 -     g.setColour (Colour (0xe5ffffff));
 -     g.fillRect (boxArea);
 - 
 -     g.setColour (Colour (0x80000000));
 -     g.drawRect (boxArea);
 - 
 -     auto size = (float) boxSize * 0.5f + 1.0f;
 -     auto centre = (float) (boxSize / 2);
 - 
 -     g.fillRect ((float) x + ((float) boxSize - size) * 0.5f, (float) y + centre, size, 1.0f);
 - 
 -     if (! isOpen)
 -         g.fillRect ((float) x + centre, (float) y + ((float) boxSize - size) * 0.5f, 1.0f, size);
 - }
 - 
 - bool LookAndFeel_V2::areLinesDrawnForTreeView (TreeView&)
 - {
 -     return true;
 - }
 - 
 - int LookAndFeel_V2::getTreeViewIndentSize (TreeView&)
 - {
 -     return 24;
 - }
 - 
 - //==============================================================================
 - void LookAndFeel_V2::drawBubble (Graphics& g, BubbleComponent& comp,
 -                                  const Point<float>& tip, const Rectangle<float>& body)
 - {
 -     Path p;
 -     p.addBubble (body.reduced (0.5f), body.getUnion (Rectangle<float> (tip.x, tip.y, 1.0f, 1.0f)),
 -                  tip, 5.0f, jmin (15.0f, body.getWidth() * 0.2f, body.getHeight() * 0.2f));
 - 
 -     g.setColour (comp.findColour (BubbleComponent::backgroundColourId));
 -     g.fillPath (p);
 - 
 -     g.setColour (comp.findColour (BubbleComponent::outlineColourId));
 -     g.strokePath (p, PathStrokeType (1.0f));
 - }
 - 
 - 
 - //==============================================================================
 - Font LookAndFeel_V2::getPopupMenuFont()
 - {
 -     return Font (17.0f);
 - }
 - 
 - void LookAndFeel_V2::getIdealPopupMenuItemSize (const String& text, const bool isSeparator,
 -                                                 int standardMenuItemHeight, int& idealWidth, int& idealHeight)
 - {
 -     if (isSeparator)
 -     {
 -         idealWidth = 50;
 -         idealHeight = standardMenuItemHeight > 0 ? standardMenuItemHeight / 2 : 10;
 -     }
 -     else
 -     {
 -         Font font (getPopupMenuFont());
 - 
 -         if (standardMenuItemHeight > 0 && font.getHeight() > (float) standardMenuItemHeight / 1.3f)
 -             font.setHeight ((float) standardMenuItemHeight / 1.3f);
 - 
 -         idealHeight = standardMenuItemHeight > 0 ? standardMenuItemHeight : roundToInt (font.getHeight() * 1.3f);
 -         idealWidth = font.getStringWidth (text) + idealHeight * 2;
 -     }
 - }
 - 
 - void LookAndFeel_V2::drawPopupMenuBackground (Graphics& g, int width, int height)
 - {
 -     auto background = findColour (PopupMenu::backgroundColourId);
 - 
 -     g.fillAll (background);
 -     g.setColour (background.overlaidWith (Colour (0x2badd8e6)));
 - 
 -     for (int i = 0; i < height; i += 3)
 -         g.fillRect (0, i, width, 1);
 - 
 -    #if ! JUCE_MAC
 -     g.setColour (findColour (PopupMenu::textColourId).withAlpha (0.6f));
 -     g.drawRect (0, 0, width, height);
 -    #endif
 - }
 - 
 - void LookAndFeel_V2::drawPopupMenuUpDownArrow (Graphics& g, int width, int height, bool isScrollUpArrow)
 - {
 -     auto background = findColour (PopupMenu::backgroundColourId);
 - 
 -     g.setGradientFill (ColourGradient (background, 0.0f, (float) height * 0.5f,
 -                                        background.withAlpha (0.0f),
 -                                        0.0f, isScrollUpArrow ? ((float) height) : 0.0f,
 -                                        false));
 - 
 -     g.fillRect (1, 1, width - 2, height - 2);
 - 
 -     auto hw = (float) width * 0.5f;
 -     auto arrowW = (float) height * 0.3f;
 -     auto y1 = (float) height * (isScrollUpArrow ? 0.6f : 0.3f);
 -     auto y2 = (float) height * (isScrollUpArrow ? 0.3f : 0.6f);
 - 
 -     Path p;
 -     p.addTriangle (hw - arrowW, y1,
 -                    hw + arrowW, y1,
 -                    hw, y2);
 - 
 -     g.setColour (findColour (PopupMenu::textColourId).withAlpha (0.5f));
 -     g.fillPath (p);
 - }
 - 
 - void LookAndFeel_V2::drawPopupMenuItem (Graphics& g, const Rectangle<int>& area,
 -                                         const bool isSeparator, const bool isActive,
 -                                         const bool isHighlighted, const bool isTicked,
 -                                         const bool hasSubMenu, const String& text,
 -                                         const String& shortcutKeyText,
 -                                         const Drawable* icon, const Colour* const textColourToUse)
 - {
 -     if (isSeparator)
 -     {
 -         auto r = area.reduced (5, 0);
 -         r.removeFromTop (r.getHeight() / 2 - 1);
 - 
 -         g.setColour (Colour (0x33000000));
 -         g.fillRect (r.removeFromTop (1));
 - 
 -         g.setColour (Colour (0x66ffffff));
 -         g.fillRect (r.removeFromTop (1));
 -     }
 -     else
 -     {
 -         auto textColour = findColour (PopupMenu::textColourId);
 - 
 -         if (textColourToUse != nullptr)
 -             textColour = *textColourToUse;
 - 
 -         auto r = area.reduced (1);
 - 
 -         if (isHighlighted)
 -         {
 -             g.setColour (findColour (PopupMenu::highlightedBackgroundColourId));
 -             g.fillRect (r);
 - 
 -             g.setColour (findColour (PopupMenu::highlightedTextColourId));
 -         }
 -         else
 -         {
 -             g.setColour (textColour);
 -         }
 - 
 -         if (! isActive)
 -             g.setOpacity (0.3f);
 - 
 -         Font font (getPopupMenuFont());
 - 
 -         auto maxFontHeight = (float) area.getHeight() / 1.3f;
 - 
 -         if (font.getHeight() > maxFontHeight)
 -             font.setHeight (maxFontHeight);
 - 
 -         g.setFont (font);
 - 
 -         auto iconArea = r.removeFromLeft ((r.getHeight() * 5) / 4).reduced (3).toFloat();
 - 
 -         if (icon != nullptr)
 -         {
 -             icon->drawWithin (g, iconArea, RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize, 1.0f);
 -         }
 -         else if (isTicked)
 -         {
 -             auto tick = getTickShape (1.0f);
 -             g.fillPath (tick, tick.getTransformToScaleToFit (iconArea, true));
 -         }
 - 
 -         if (hasSubMenu)
 -         {
 -             auto arrowH = 0.6f * getPopupMenuFont().getAscent();
 - 
 -             auto x = (float) r.removeFromRight ((int) arrowH).getX();
 -             auto halfH = (float) r.getCentreY();
 - 
 -             Path p;
 -             p.addTriangle (x, halfH - arrowH * 0.5f,
 -                            x, halfH + arrowH * 0.5f,
 -                            x + arrowH * 0.6f, halfH);
 - 
 -             g.fillPath (p);
 -         }
 - 
 -         r.removeFromRight (3);
 -         g.drawFittedText (text, r, Justification::centredLeft, 1);
 - 
 -         if (shortcutKeyText.isNotEmpty())
 -         {
 -             Font f2 (font);
 -             f2.setHeight (f2.getHeight() * 0.75f);
 -             f2.setHorizontalScale (0.95f);
 -             g.setFont (f2);
 - 
 -             g.drawText (shortcutKeyText, r, Justification::centredRight, true);
 -         }
 -     }
 - }
 - 
 - void LookAndFeel_V2::drawPopupMenuSectionHeader (Graphics& g, const Rectangle<int>& area, const String& sectionName)
 - {
 -     g.setFont (getPopupMenuFont().boldened());
 -     g.setColour (findColour (PopupMenu::headerTextColourId));
 - 
 -     g.drawFittedText (sectionName,
 -                       area.getX() + 12, area.getY(), area.getWidth() - 16, (int) ((float) area.getHeight() * 0.8f),
 -                       Justification::bottomLeft, 1);
 - }
 - 
 - //==============================================================================
 - int LookAndFeel_V2::getMenuWindowFlags()
 - {
 -     return ComponentPeer::windowHasDropShadow;
 - }
 - 
 - void LookAndFeel_V2::drawMenuBarBackground (Graphics& g, int width, int height, bool, MenuBarComponent& menuBar)
 - {
 -     auto baseColour = LookAndFeelHelpers::createBaseColour (menuBar.findColour (PopupMenu::backgroundColourId),
 -                                                             false, false, false);
 - 
 -     if (menuBar.isEnabled())
 -         drawShinyButtonShape (g, -4.0f, 0.0f, (float) width + 8.0f, (float) height,
 -                               0.0f, baseColour, 0.4f, true, true, true, true);
 -     else
 -         g.fillAll (baseColour);
 - }
 - 
 - Font LookAndFeel_V2::getMenuBarFont (MenuBarComponent& menuBar, int /*itemIndex*/, const String& /*itemText*/)
 - {
 -     return Font ((float) menuBar.getHeight() * 0.7f);
 - }
 - 
 - int LookAndFeel_V2::getMenuBarItemWidth (MenuBarComponent& menuBar, int itemIndex, const String& itemText)
 - {
 -     return getMenuBarFont (menuBar, itemIndex, itemText)
 -             .getStringWidth (itemText) + menuBar.getHeight();
 - }
 - 
 - void LookAndFeel_V2::drawMenuBarItem (Graphics& g, int width, int height,
 -                                       int itemIndex, const String& itemText,
 -                                       bool isMouseOverItem, bool isMenuOpen,
 -                                       bool /*isMouseOverBar*/, MenuBarComponent& menuBar)
 - {
 -     if (! menuBar.isEnabled())
 -     {
 -         g.setColour (menuBar.findColour (PopupMenu::textColourId)
 -                             .withMultipliedAlpha (0.5f));
 -     }
 -     else if (isMenuOpen || isMouseOverItem)
 -     {
 -         g.fillAll (menuBar.findColour (PopupMenu::highlightedBackgroundColourId));
 -         g.setColour (menuBar.findColour (PopupMenu::highlightedTextColourId));
 -     }
 -     else
 -     {
 -         g.setColour (menuBar.findColour (PopupMenu::textColourId));
 -     }
 - 
 -     g.setFont (getMenuBarFont (menuBar, itemIndex, itemText));
 -     g.drawFittedText (itemText, 0, 0, width, height, Justification::centred, 1);
 - }
 - 
 - Component* LookAndFeel_V2::getParentComponentForMenuOptions (const PopupMenu::Options& options)
 - {
 -     return options.getParentComponent();
 - }
 - 
 - void LookAndFeel_V2::preparePopupMenuWindow (Component&) {}
 - 
 - bool LookAndFeel_V2::shouldPopupMenuScaleWithTargetComponent (const PopupMenu::Options&)    { return true; }
 - 
 - int LookAndFeel_V2::getPopupMenuBorderSize()    { return 2; }
 - 
 - //==============================================================================
 - void LookAndFeel_V2::fillTextEditorBackground (Graphics& g, int /*width*/, int /*height*/, TextEditor& textEditor)
 - {
 -     g.fillAll (textEditor.findColour (TextEditor::backgroundColourId));
 - }
 - 
 - void LookAndFeel_V2::drawTextEditorOutline (Graphics& g, int width, int height, TextEditor& textEditor)
 - {
 -     if (textEditor.isEnabled())
 -     {
 -         if (textEditor.hasKeyboardFocus (true) && ! textEditor.isReadOnly())
 -         {
 -             const int border = 2;
 - 
 -             g.setColour (textEditor.findColour (TextEditor::focusedOutlineColourId));
 -             g.drawRect (0, 0, width, height, border);
 - 
 -             g.setOpacity (1.0f);
 -             auto shadowColour = textEditor.findColour (TextEditor::shadowColourId).withMultipliedAlpha (0.75f);
 -             drawBevel (g, 0, 0, width, height + 2, border + 2, shadowColour, shadowColour);
 -         }
 -         else
 -         {
 -             g.setColour (textEditor.findColour (TextEditor::outlineColourId));
 -             g.drawRect (0, 0, width, height);
 - 
 -             g.setOpacity (1.0f);
 -             auto shadowColour = textEditor.findColour (TextEditor::shadowColourId);
 -             drawBevel (g, 0, 0, width, height + 2, 3, shadowColour, shadowColour);
 -         }
 -     }
 - }
 - 
 - CaretComponent* LookAndFeel_V2::createCaretComponent (Component* keyFocusOwner)
 - {
 -     return new CaretComponent (keyFocusOwner);
 - }
 - 
 - //==============================================================================
 - void LookAndFeel_V2::drawComboBox (Graphics& g, int width, int height, const bool isMouseButtonDown,
 -                                    int buttonX, int buttonY, int buttonW, int buttonH, ComboBox& box)
 - {
 -     g.fillAll (box.findColour (ComboBox::backgroundColourId));
 - 
 -     if (box.isEnabled() && box.hasKeyboardFocus (false))
 -     {
 -         g.setColour (box.findColour (ComboBox::focusedOutlineColourId));
 -         g.drawRect (0, 0, width, height, 2);
 -     }
 -     else
 -     {
 -         g.setColour (box.findColour (ComboBox::outlineColourId));
 -         g.drawRect (0, 0, width, height);
 -     }
 - 
 -     auto outlineThickness = box.isEnabled() ? (isMouseButtonDown ? 1.2f : 0.5f) : 0.3f;
 - 
 -     auto baseColour = LookAndFeelHelpers::createBaseColour (box.findColour (ComboBox::buttonColourId),
 -                                                             box.hasKeyboardFocus (true),
 -                                                             false, isMouseButtonDown)
 -                          .withMultipliedAlpha (box.isEnabled() ? 1.0f : 0.5f);
 - 
 -     drawGlassLozenge (g,
 -                       (float) buttonX + outlineThickness, (float) buttonY + outlineThickness,
 -                       (float) buttonW - outlineThickness * 2.0f, (float) buttonH - outlineThickness * 2.0f,
 -                       baseColour, outlineThickness, -1.0f,
 -                       true, true, true, true);
 - 
 -     if (box.isEnabled())
 -     {
 -         const float arrowX = 0.3f;
 -         const float arrowH = 0.2f;
 - 
 -         const auto x = (float) buttonX;
 -         const auto y = (float) buttonY;
 -         const auto w = (float) buttonW;
 -         const auto h = (float) buttonH;
 - 
 -         Path p;
 -         p.addTriangle (x + w * 0.5f,            y + h * (0.45f - arrowH),
 -                        x + w * (1.0f - arrowX), y + h * 0.45f,
 -                        x + w * arrowX,          y + h * 0.45f);
 - 
 -         p.addTriangle (x + w * 0.5f,            y + h * (0.55f + arrowH),
 -                        x + w * (1.0f - arrowX), y + h * 0.55f,
 -                        x + w * arrowX,          y + h * 0.55f);
 - 
 -         g.setColour (box.findColour (ComboBox::arrowColourId));
 -         g.fillPath (p);
 -     }
 - }
 - 
 - Font LookAndFeel_V2::getComboBoxFont (ComboBox& box)
 - {
 -     return Font (jmin (15.0f, (float) box.getHeight() * 0.85f));
 - }
 - 
 - Label* LookAndFeel_V2::createComboBoxTextBox (ComboBox&)
 - {
 -     return new Label (String(), String());
 - }
 - 
 - void LookAndFeel_V2::positionComboBoxText (ComboBox& box, Label& label)
 - {
 -     label.setBounds (1, 1,
 -                      box.getWidth() + 3 - box.getHeight(),
 -                      box.getHeight() - 2);
 - 
 -     label.setFont (getComboBoxFont (box));
 - }
 - 
 - PopupMenu::Options LookAndFeel_V2::getOptionsForComboBoxPopupMenu (ComboBox& box, Label& label)
 - {
 -     return PopupMenu::Options().withTargetComponent (&box)
 -                                .withItemThatMustBeVisible (box.getSelectedId())
 -                                .withMinimumWidth (box.getWidth())
 -                                .withMaximumNumColumns (1)
 -                                .withStandardItemHeight (label.getHeight());
 - }
 - 
 - void LookAndFeel_V2::drawComboBoxTextWhenNothingSelected (Graphics& g, ComboBox& box, Label& label)
 - {
 -     g.setColour (findColour (ComboBox::textColourId).withMultipliedAlpha (0.5f));
 - 
 -     auto font = label.getLookAndFeel().getLabelFont (label);
 - 
 -     g.setFont (font);
 - 
 -     auto textArea = getLabelBorderSize (label).subtractedFrom (label.getLocalBounds());
 - 
 -     g.drawFittedText (box.getTextWhenNothingSelected(), textArea, label.getJustificationType(),
 -                       jmax (1, (int) ((float) textArea.getHeight() / font.getHeight())),
 -                       label.getMinimumHorizontalScale());
 - }
 - 
 - //==============================================================================
 - Font LookAndFeel_V2::getLabelFont (Label& label)
 - {
 -     return label.getFont();
 - }
 - 
 - void LookAndFeel_V2::drawLabel (Graphics& g, Label& label)
 - {
 -     g.fillAll (label.findColour (Label::backgroundColourId));
 - 
 -     if (! label.isBeingEdited())
 -     {
 -         auto alpha = label.isEnabled() ? 1.0f : 0.5f;
 -         const Font font (getLabelFont (label));
 - 
 -         g.setColour (label.findColour (Label::textColourId).withMultipliedAlpha (alpha));
 -         g.setFont (font);
 - 
 -         auto textArea = getLabelBorderSize (label).subtractedFrom (label.getLocalBounds());
 - 
 -         g.drawFittedText (label.getText(), textArea, label.getJustificationType(),
 -                           jmax (1, (int) ((float) textArea.getHeight() / font.getHeight())),
 -                           label.getMinimumHorizontalScale());
 - 
 -         g.setColour (label.findColour (Label::outlineColourId).withMultipliedAlpha (alpha));
 -     }
 -     else if (label.isEnabled())
 -     {
 -         g.setColour (label.findColour (Label::outlineColourId));
 -     }
 - 
 -     g.drawRect (label.getLocalBounds());
 - }
 - 
 - BorderSize<int> LookAndFeel_V2::getLabelBorderSize (Label& label)
 - {
 -     return label.getBorderSize();
 - }
 - 
 - //==============================================================================
 - void LookAndFeel_V2::drawLinearSliderBackground (Graphics& g, int x, int y, int width, int height,
 -                                                  float /*sliderPos*/,
 -                                                  float /*minSliderPos*/,
 -                                                  float /*maxSliderPos*/,
 -                                                  const Slider::SliderStyle /*style*/, Slider& slider)
 - {
 -     auto sliderRadius = (float) (getSliderThumbRadius (slider) - 2);
 -     auto trackColour = slider.findColour (Slider::trackColourId);
 -     auto gradCol1 = trackColour.overlaidWith (Colours::black.withAlpha (slider.isEnabled() ? 0.25f : 0.13f));
 -     auto gradCol2 = trackColour.overlaidWith (Colour (0x14000000));
 - 
 -     Path indent;
 - 
 -     if (slider.isHorizontal())
 -     {
 -         const float iy = (float) y + (float) height * 0.5f - sliderRadius * 0.5f;
 -         const float ih = sliderRadius;
 - 
 -         g.setGradientFill (ColourGradient::vertical (gradCol1, iy, gradCol2, iy + ih));
 - 
 -         indent.addRoundedRectangle ((float) x - sliderRadius * 0.5f, iy,
 -                                     (float) width + sliderRadius, ih,
 -                                     5.0f);
 -     }
 -     else
 -     {
 -         const float ix = (float) x + (float) width * 0.5f - sliderRadius * 0.5f;
 -         const float iw = sliderRadius;
 - 
 -         g.setGradientFill (ColourGradient::horizontal (gradCol1, ix, gradCol2, ix + iw));
 - 
 -         indent.addRoundedRectangle (ix, (float) y - sliderRadius * 0.5f,
 -                                     iw, (float) height + sliderRadius,
 -                                     5.0f);
 -     }
 - 
 -     g.fillPath (indent);
 - 
 -     g.setColour (Colour (0x4c000000));
 -     g.strokePath (indent, PathStrokeType (0.5f));
 - }
 - 
 - void LookAndFeel_V2::drawLinearSliderThumb (Graphics& g, int x, int y, int width, int height,
 -                                             float sliderPos, float minSliderPos, float maxSliderPos,
 -                                             const Slider::SliderStyle style, Slider& slider)
 - {
 -     auto sliderRadius = (float) (getSliderThumbRadius (slider) - 2);
 - 
 -     auto knobColour = LookAndFeelHelpers::createBaseColour (slider.findColour (Slider::thumbColourId),
 -                                                             slider.hasKeyboardFocus (false) && slider.isEnabled(),
 -                                                             slider.isMouseOverOrDragging() && slider.isEnabled(),
 -                                                             slider.isMouseButtonDown() && slider.isEnabled());
 - 
 -     const float outlineThickness = slider.isEnabled() ? 0.8f : 0.3f;
 - 
 -     if (style == Slider::LinearHorizontal || style == Slider::LinearVertical)
 -     {
 -         float kx, ky;
 - 
 -         if (style == Slider::LinearVertical)
 -         {
 -             kx = (float) x + (float) width * 0.5f;
 -             ky = sliderPos;
 -         }
 -         else
 -         {
 -             kx = sliderPos;
 -             ky = (float) y + (float) height * 0.5f;
 -         }
 - 
 -         drawGlassSphere (g,
 -                          kx - sliderRadius,
 -                          ky - sliderRadius,
 -                          sliderRadius * 2.0f,
 -                          knobColour, outlineThickness);
 -     }
 -     else
 -     {
 -         if (style == Slider::ThreeValueVertical)
 -         {
 -             drawGlassSphere (g, (float) x + (float) width * 0.5f - sliderRadius,
 -                              sliderPos - sliderRadius,
 -                              sliderRadius * 2.0f,
 -                              knobColour, outlineThickness);
 -         }
 -         else if (style == Slider::ThreeValueHorizontal)
 -         {
 -             drawGlassSphere (g,sliderPos - sliderRadius,
 -                              (float) y + (float) height * 0.5f - sliderRadius,
 -                              sliderRadius * 2.0f,
 -                              knobColour, outlineThickness);
 -         }
 - 
 -         if (style == Slider::TwoValueVertical || style == Slider::ThreeValueVertical)
 -         {
 -             auto sr = jmin (sliderRadius, (float) width * 0.4f);
 - 
 -             drawGlassPointer (g, jmax (0.0f, (float) x + (float) width * 0.5f - sliderRadius * 2.0f),
 -                               minSliderPos - sliderRadius,
 -                               sliderRadius * 2.0f, knobColour, outlineThickness, 1);
 - 
 -             drawGlassPointer (g,
 -                               jmin ((float) x + (float) width - sliderRadius * 2.0f,
 -                                     (float) x + (float) width * 0.5f),
 -                               maxSliderPos - sr,
 -                               sliderRadius * 2.0f,
 -                               knobColour,
 -                               outlineThickness,
 -                               3);
 -         }
 -         else if (style == Slider::TwoValueHorizontal || style == Slider::ThreeValueHorizontal)
 -         {
 -             auto sr = jmin (sliderRadius, (float) height * 0.4f);
 - 
 -             drawGlassPointer (g, minSliderPos - sr,
 -                               jmax (0.0f, (float) y + (float) height * 0.5f - sliderRadius * 2.0f),
 -                               sliderRadius * 2.0f, knobColour, outlineThickness, 2);
 - 
 -             drawGlassPointer (g,
 -                               maxSliderPos - sliderRadius,
 -                               jmin ((float) y + (float) height - sliderRadius * 2.0f,
 -                                     (float) y + (float) height * 0.5f),
 -                               sliderRadius * 2.0f,
 -                               knobColour,
 -                               outlineThickness,
 -                               4);
 -         }
 -     }
 - }
 - 
 - void LookAndFeel_V2::drawLinearSlider (Graphics& g, int x, int y, int width, int height,
 -                                        float sliderPos, float minSliderPos, float maxSliderPos,
 -                                        const Slider::SliderStyle style, Slider& slider)
 - {
 -     g.fillAll (slider.findColour (Slider::backgroundColourId));
 - 
 -     if (style == Slider::LinearBar || style == Slider::LinearBarVertical)
 -     {
 -         const bool isMouseOver = slider.isMouseOverOrDragging() && slider.isEnabled();
 - 
 -         auto baseColour = LookAndFeelHelpers::createBaseColour (slider.findColour (Slider::thumbColourId)
 -                                                                       .withMultipliedSaturation (slider.isEnabled() ? 1.0f : 0.5f),
 -                                                                 false, isMouseOver,
 -                                                                 isMouseOver || slider.isMouseButtonDown());
 - 
 -         drawShinyButtonShape (g,
 -                               (float) x,
 -                               style == Slider::LinearBarVertical ? sliderPos
 -                                                                  : (float) y,
 -                               style == Slider::LinearBarVertical ? (float) width
 -                                                                  : (sliderPos - (float) x),
 -                               style == Slider::LinearBarVertical ? ((float) height - sliderPos)
 -                                                                  : (float) height, 0.0f,
 -                               baseColour,
 -                               slider.isEnabled() ? 0.9f : 0.3f,
 -                               true, true, true, true);
 -     }
 -     else
 -     {
 -         drawLinearSliderBackground (g, x, y, width, height, sliderPos, minSliderPos, maxSliderPos, style, slider);
 -         drawLinearSliderThumb (g, x, y, width, height, sliderPos, minSliderPos, maxSliderPos, style, slider);
 -     }
 - }
 - 
 - int LookAndFeel_V2::getSliderThumbRadius (Slider& slider)
 - {
 -     return jmin (7,
 -                  slider.getHeight() / 2,
 -                  slider.getWidth() / 2) + 2;
 - }
 - 
 - void LookAndFeel_V2::drawRotarySlider (Graphics& g, int x, int y, int width, int height, float sliderPos,
 -                                        const float rotaryStartAngle, const float rotaryEndAngle, Slider& slider)
 - {
 -     const float radius = jmin ((float) width * 0.5f, (float) height * 0.5f) - 2.0f;
 -     const float centreX = (float) x + (float) width * 0.5f;
 -     const float centreY = (float) y + (float) height * 0.5f;
 -     const float rx = centreX - radius;
 -     const float ry = centreY - radius;
 -     const float rw = radius * 2.0f;
 -     const float angle = rotaryStartAngle + sliderPos * (rotaryEndAngle - rotaryStartAngle);
 -     const bool isMouseOver = slider.isMouseOverOrDragging() && slider.isEnabled();
 - 
 -     if (radius > 12.0f)
 -     {
 -         if (slider.isEnabled())
 -             g.setColour (slider.findColour (Slider::rotarySliderFillColourId).withAlpha (isMouseOver ? 1.0f : 0.7f));
 -         else
 -             g.setColour (Colour (0x80808080));
 - 
 -         const float thickness = 0.7f;
 - 
 -         {
 -             Path filledArc;
 -             filledArc.addPieSegment (rx, ry, rw, rw, rotaryStartAngle, angle, thickness);
 -             g.fillPath (filledArc);
 -         }
 - 
 -         {
 -             const float innerRadius = radius * 0.2f;
 -             Path p;
 -             p.addTriangle (-innerRadius, 0.0f,
 -                            0.0f, -radius * thickness * 1.1f,
 -                            innerRadius, 0.0f);
 - 
 -             p.addEllipse (-innerRadius, -innerRadius, innerRadius * 2.0f, innerRadius * 2.0f);
 - 
 -             g.fillPath (p, AffineTransform::rotation (angle).translated (centreX, centreY));
 -         }
 - 
 -         if (slider.isEnabled())
 -             g.setColour (slider.findColour (Slider::rotarySliderOutlineColourId));
 -         else
 -             g.setColour (Colour (0x80808080));
 - 
 -         Path outlineArc;
 -         outlineArc.addPieSegment (rx, ry, rw, rw, rotaryStartAngle, rotaryEndAngle, thickness);
 -         outlineArc.closeSubPath();
 - 
 -         g.strokePath (outlineArc, PathStrokeType (slider.isEnabled() ? (isMouseOver ? 2.0f : 1.2f) : 0.3f));
 -     }
 -     else
 -     {
 -         if (slider.isEnabled())
 -             g.setColour (slider.findColour (Slider::rotarySliderFillColourId).withAlpha (isMouseOver ? 1.0f : 0.7f));
 -         else
 -             g.setColour (Colour (0x80808080));
 - 
 -         Path p;
 -         p.addEllipse (-0.4f * rw, -0.4f * rw, rw * 0.8f, rw * 0.8f);
 -         PathStrokeType (rw * 0.1f).createStrokedPath (p, p);
 - 
 -         p.addLineSegment (Line<float> (0.0f, 0.0f, 0.0f, -radius), rw * 0.2f);
 - 
 -         g.fillPath (p, AffineTransform::rotation (angle).translated (centreX, centreY));
 -     }
 - }
 - 
 - Button* LookAndFeel_V2::createSliderButton (Slider&, const bool isIncrement)
 - {
 -     return new TextButton (isIncrement ? "+" : "-", String());
 - }
 - 
 - class LookAndFeel_V2::SliderLabelComp  : public Label
 - {
 - public:
 -     SliderLabelComp() : Label ({}, {}) {}
 - 
 -     void mouseWheelMove (const MouseEvent&, const MouseWheelDetails&) override {}
 - };
 - 
 - Label* LookAndFeel_V2::createSliderTextBox (Slider& slider)
 - {
 -     auto l = new SliderLabelComp();
 - 
 -     l->setJustificationType (Justification::centred);
 -     l->setKeyboardType (TextInputTarget::decimalKeyboard);
 - 
 -     l->setColour (Label::textColourId, slider.findColour (Slider::textBoxTextColourId));
 -     l->setColour (Label::backgroundColourId,
 -                   (slider.getSliderStyle() == Slider::LinearBar || slider.getSliderStyle() == Slider::LinearBarVertical)
 -                             ? Colours::transparentBlack
 -                             : slider.findColour (Slider::textBoxBackgroundColourId));
 -     l->setColour (Label::outlineColourId, slider.findColour (Slider::textBoxOutlineColourId));
 -     l->setColour (TextEditor::textColourId, slider.findColour (Slider::textBoxTextColourId));
 -     l->setColour (TextEditor::backgroundColourId,
 -                   slider.findColour (Slider::textBoxBackgroundColourId)
 -                         .withAlpha ((slider.getSliderStyle() == Slider::LinearBar || slider.getSliderStyle() == Slider::LinearBarVertical)
 -                                         ? 0.7f : 1.0f));
 -     l->setColour (TextEditor::outlineColourId, slider.findColour (Slider::textBoxOutlineColourId));
 -     l->setColour (TextEditor::highlightColourId, slider.findColour (Slider::textBoxHighlightColourId));
 - 
 -     return l;
 - }
 - 
 - ImageEffectFilter* LookAndFeel_V2::getSliderEffect (Slider&)
 - {
 -     return nullptr;
 - }
 - 
 - Font LookAndFeel_V2::getSliderPopupFont (Slider&)
 - {
 -     return Font (15.0f, Font::bold);
 - }
 - 
 - int LookAndFeel_V2::getSliderPopupPlacement (Slider&)
 - {
 -     return BubbleComponent::above
 -             | BubbleComponent::below
 -             | BubbleComponent::left
 -             | BubbleComponent::right;
 - }
 - 
 - //==============================================================================
 - Slider::SliderLayout LookAndFeel_V2::getSliderLayout (Slider& slider)
 - {
 -     // 1. compute the actually visible textBox size from the slider textBox size and some additional constraints
 - 
 -     int minXSpace = 0;
 -     int minYSpace = 0;
 - 
 -     auto textBoxPos = slider.getTextBoxPosition();
 - 
 -     if (textBoxPos == Slider::TextBoxLeft || textBoxPos == Slider::TextBoxRight)
 -         minXSpace = 30;
 -     else
 -         minYSpace = 15;
 - 
 -     auto localBounds = slider.getLocalBounds();
 - 
 -     auto textBoxWidth  = jmax (0, jmin (slider.getTextBoxWidth(),  localBounds.getWidth() - minXSpace));
 -     auto textBoxHeight = jmax (0, jmin (slider.getTextBoxHeight(), localBounds.getHeight() - minYSpace));
 - 
 -     Slider::SliderLayout layout;
 - 
 -     // 2. set the textBox bounds
 - 
 -     if (textBoxPos != Slider::NoTextBox)
 -     {
 -         if (slider.isBar())
 -         {
 -             layout.textBoxBounds = localBounds;
 -         }
 -         else
 -         {
 -             layout.textBoxBounds.setWidth (textBoxWidth);
 -             layout.textBoxBounds.setHeight (textBoxHeight);
 - 
 -             if (textBoxPos == Slider::TextBoxLeft)           layout.textBoxBounds.setX (0);
 -             else if (textBoxPos == Slider::TextBoxRight)     layout.textBoxBounds.setX (localBounds.getWidth() - textBoxWidth);
 -             else /* above or below -> centre horizontally */ layout.textBoxBounds.setX ((localBounds.getWidth() - textBoxWidth) / 2);
 - 
 -             if (textBoxPos == Slider::TextBoxAbove)          layout.textBoxBounds.setY (0);
 -             else if (textBoxPos == Slider::TextBoxBelow)     layout.textBoxBounds.setY (localBounds.getHeight() - textBoxHeight);
 -             else /* left or right -> centre vertically */    layout.textBoxBounds.setY ((localBounds.getHeight() - textBoxHeight) / 2);
 -         }
 -     }
 - 
 -     // 3. set the slider bounds
 - 
 -     layout.sliderBounds = localBounds;
 - 
 -     if (slider.isBar())
 -     {
 -         layout.sliderBounds.reduce (1, 1);   // bar border
 -     }
 -     else
 -     {
 -         if (textBoxPos == Slider::TextBoxLeft)       layout.sliderBounds.removeFromLeft (textBoxWidth);
 -         else if (textBoxPos == Slider::TextBoxRight) layout.sliderBounds.removeFromRight (textBoxWidth);
 -         else if (textBoxPos == Slider::TextBoxAbove) layout.sliderBounds.removeFromTop (textBoxHeight);
 -         else if (textBoxPos == Slider::TextBoxBelow) layout.sliderBounds.removeFromBottom (textBoxHeight);
 - 
 -         const int thumbIndent = getSliderThumbRadius (slider);
 - 
 -         if (slider.isHorizontal())    layout.sliderBounds.reduce (thumbIndent, 0);
 -         else if (slider.isVertical()) layout.sliderBounds.reduce (0, thumbIndent);
 -     }
 - 
 -     return layout;
 - }
 - 
 - //==============================================================================
 - Rectangle<int> LookAndFeel_V2::getTooltipBounds (const String& tipText, Point<int> screenPos, Rectangle<int> parentArea)
 - {
 -     const TextLayout tl (LookAndFeelHelpers::layoutTooltipText (tipText, Colours::black));
 - 
 -     auto w = (int) (tl.getWidth() + 14.0f);
 -     auto h = (int) (tl.getHeight() + 6.0f);
 - 
 -     return Rectangle<int> (screenPos.x > parentArea.getCentreX() ? screenPos.x - (w + 12) : screenPos.x + 24,
 -                            screenPos.y > parentArea.getCentreY() ? screenPos.y - (h + 6)  : screenPos.y + 6,
 -                            w, h)
 -              .constrainedWithin (parentArea);
 - }
 - 
 - void LookAndFeel_V2::drawTooltip (Graphics& g, const String& text, int width, int height)
 - {
 -     g.fillAll (findColour (TooltipWindow::backgroundColourId));
 - 
 -    #if ! JUCE_MAC // The mac windows already have a non-optional 1 pix outline, so don't double it here..
 -     g.setColour (findColour (TooltipWindow::outlineColourId));
 -     g.drawRect (0, 0, width, height, 1);
 -    #endif
 - 
 -     LookAndFeelHelpers::layoutTooltipText (text, findColour (TooltipWindow::textColourId))
 -         .draw (g, Rectangle<float> ((float) width, (float) height));
 - }
 - 
 - //==============================================================================
 - Button* LookAndFeel_V2::createFilenameComponentBrowseButton (const String& text)
 - {
 -     return new TextButton (text, TRANS("click to browse for a different file"));
 - }
 - 
 - void LookAndFeel_V2::layoutFilenameComponent (FilenameComponent& filenameComp,
 -                                               ComboBox* filenameBox, Button* browseButton)
 - {
 -     browseButton->setSize (80, filenameComp.getHeight());
 - 
 -     if (auto* tb = dynamic_cast<TextButton*> (browseButton))
 -         tb->changeWidthToFitText();
 - 
 -     browseButton->setTopRightPosition (filenameComp.getWidth(), 0);
 - 
 -     filenameBox->setBounds (0, 0, browseButton->getX(), filenameComp.getHeight());
 - }
 - 
 - //==============================================================================
 - void LookAndFeel_V2::drawConcertinaPanelHeader (Graphics& g, const Rectangle<int>& area,
 -                                                 bool isMouseOver, bool /*isMouseDown*/,
 -                                                 ConcertinaPanel&, Component& panel)
 - {
 -     g.fillAll (Colours::grey.withAlpha (isMouseOver ? 0.9f : 0.7f));
 -     g.setColour (Colours::black.withAlpha (0.5f));
 -     g.drawRect (area);
 - 
 -     g.setColour (Colours::white);
 -     g.setFont (Font ((float) area.getHeight() * 0.7f).boldened());
 -     g.drawFittedText (panel.getName(), 4, 0, area.getWidth() - 6, area.getHeight(), Justification::centredLeft, 1);
 - }
 - 
 - //==============================================================================
 - void LookAndFeel_V2::drawImageButton (Graphics& g, Image* image,
 -                                       int imageX, int imageY, int imageW, int imageH,
 -                                       const Colour& overlayColour,
 -                                       float imageOpacity,
 -                                       ImageButton& button)
 - {
 -     if (! button.isEnabled())
 -         imageOpacity *= 0.3f;
 - 
 -     AffineTransform t = RectanglePlacement (RectanglePlacement::stretchToFit)
 -                             .getTransformToFit (image->getBounds().toFloat(),
 -                                                 Rectangle<int> (imageX, imageY, imageW, imageH).toFloat());
 - 
 -     if (! overlayColour.isOpaque())
 -     {
 -         g.setOpacity (imageOpacity);
 -         g.drawImageTransformed (*image, t, false);
 -     }
 - 
 -     if (! overlayColour.isTransparent())
 -     {
 -         g.setColour (overlayColour);
 -         g.drawImageTransformed (*image, t, true);
 -     }
 - }
 - 
 - //==============================================================================
 - void LookAndFeel_V2::drawCornerResizer (Graphics& g, int w, int h, bool /*isMouseOver*/, bool /*isMouseDragging*/)
 - {
 -     auto lineThickness = jmin ((float) w, (float) h) * 0.075f;
 - 
 -     for (float i = 0.0f; i < 1.0f; i += 0.3f)
 -     {
 -         g.setColour (Colours::lightgrey);
 - 
 -         g.drawLine ((float) w * i,
 -                     (float) h + 1.0f,
 -                     (float) w + 1.0f,
 -                     (float) h * i,
 -                     lineThickness);
 - 
 -         g.setColour (Colours::darkgrey);
 - 
 -         g.drawLine ((float) w * i + lineThickness,
 -                     (float) h + 1.0f,
 -                     (float) w + 1.0f,
 -                     (float) h * i + lineThickness,
 -                     lineThickness);
 -     }
 - }
 - 
 - void LookAndFeel_V2::drawResizableFrame (Graphics& g, int w, int h, const BorderSize<int>& border)
 - {
 -     if (! border.isEmpty())
 -     {
 -         const Rectangle<int> fullSize (0, 0, w, h);
 -         auto centreArea = border.subtractedFrom (fullSize);
 - 
 -         Graphics::ScopedSaveState ss (g);
 - 
 -         g.excludeClipRegion (centreArea);
 - 
 -         g.setColour (Colour (0x50000000));
 -         g.drawRect (fullSize);
 - 
 -         g.setColour (Colour (0x19000000));
 -         g.drawRect (centreArea.expanded (1, 1));
 -     }
 - }
 - 
 - //==============================================================================
 - void LookAndFeel_V2::fillResizableWindowBackground (Graphics& g, int /*w*/, int /*h*/,
 -                                                     const BorderSize<int>& /*border*/, ResizableWindow& window)
 - {
 -     g.fillAll (window.getBackgroundColour());
 - }
 - 
 - void LookAndFeel_V2::drawResizableWindowBorder (Graphics&, int /*w*/, int /*h*/,
 -                                                 const BorderSize<int>& /*border*/, ResizableWindow&)
 - {
 - }
 - 
 - void LookAndFeel_V2::drawDocumentWindowTitleBar (DocumentWindow& window, Graphics& g,
 -                                                  int w, int h, int titleSpaceX, int titleSpaceW,
 -                                                  const Image* icon, bool drawTitleTextOnLeft)
 - {
 -     if (w * h == 0)
 -         return;
 - 
 -     const bool isActive = window.isActiveWindow();
 - 
 -     g.setGradientFill (ColourGradient::vertical (window.getBackgroundColour(), 0,
 -                                                  window.getBackgroundColour().contrasting (isActive ? 0.15f : 0.05f), (float) h));
 -     g.fillAll();
 - 
 -     Font font ((float) h * 0.65f, Font::bold);
 -     g.setFont (font);
 - 
 -     int textW = font.getStringWidth (window.getName());
 -     int iconW = 0;
 -     int iconH = 0;
 - 
 -     if (icon != nullptr)
 -     {
 -         iconH = (int) font.getHeight();
 -         iconW = icon->getWidth() * iconH / icon->getHeight() + 4;
 -     }
 - 
 -     textW = jmin (titleSpaceW, textW + iconW);
 -     int textX = drawTitleTextOnLeft ? titleSpaceX
 -                                     : jmax (titleSpaceX, (w - textW) / 2);
 - 
 -     if (textX + textW > titleSpaceX + titleSpaceW)
 -         textX = titleSpaceX + titleSpaceW - textW;
 - 
 -     if (icon != nullptr)
 -     {
 -         g.setOpacity (isActive ? 1.0f : 0.6f);
 -         g.drawImageWithin (*icon, textX, (h - iconH) / 2, iconW, iconH,
 -                            RectanglePlacement::centred, false);
 -         textX += iconW;
 -         textW -= iconW;
 -     }
 - 
 -     if (window.isColourSpecified (DocumentWindow::textColourId) || isColourSpecified (DocumentWindow::textColourId))
 -         g.setColour (window.findColour (DocumentWindow::textColourId));
 -     else
 -         g.setColour (window.getBackgroundColour().contrasting (isActive ? 0.7f : 0.4f));
 - 
 -     g.drawText (window.getName(), textX, 0, textW, h, Justification::centredLeft, true);
 - }
 - 
 - //==============================================================================
 - class LookAndFeel_V2::GlassWindowButton   : public Button
 - {
 - public:
 -     GlassWindowButton (const String& name, Colour col,
 -                        const Path& normalShape_,
 -                        const Path& toggledShape_) noexcept
 -         : Button (name),
 -           colour (col),
 -           normalShape (normalShape_),
 -           toggledShape (toggledShape_)
 -     {
 -     }
 - 
 -     //==============================================================================
 -     void paintButton (Graphics& g, bool shouldDrawButtonAsHighlighted, bool shouldDrawButtonAsDown) override
 -     {
 -         float alpha = shouldDrawButtonAsHighlighted ? (shouldDrawButtonAsDown ? 1.0f : 0.8f) : 0.55f;
 - 
 -         if (! isEnabled())
 -             alpha *= 0.5f;
 - 
 -         float x = 0, y = 0, diam;
 - 
 -         if (getWidth() < getHeight())
 -         {
 -             diam = (float) getWidth();
 -             y = (float) (getHeight() - getWidth()) * 0.5f;
 -         }
 -         else
 -         {
 -             diam = (float) getHeight();
 -             y = (float) (getWidth() - getHeight()) * 0.5f;
 -         }
 - 
 -         x += diam * 0.05f;
 -         y += diam * 0.05f;
 -         diam *= 0.9f;
 - 
 -         g.setGradientFill (ColourGradient (Colour::greyLevel (0.9f).withAlpha (alpha), 0, y + diam,
 -                                            Colour::greyLevel (0.6f).withAlpha (alpha), 0, y, false));
 -         g.fillEllipse (x, y, diam, diam);
 - 
 -         x += 2.0f;
 -         y += 2.0f;
 -         diam -= 4.0f;
 - 
 -         LookAndFeel_V2::drawGlassSphere (g, x, y, diam, colour.withAlpha (alpha), 1.0f);
 - 
 -         Path& p = getToggleState() ? toggledShape : normalShape;
 - 
 -         const AffineTransform t (p.getTransformToScaleToFit (x + diam * 0.3f, y + diam * 0.3f,
 -                                                              diam * 0.4f, diam * 0.4f, true));
 - 
 -         g.setColour (Colours::black.withAlpha (alpha * 0.6f));
 -         g.fillPath (p, t);
 -     }
 - 
 - private:
 -     Colour colour;
 -     Path normalShape, toggledShape;
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GlassWindowButton)
 - };
 - 
 - Button* LookAndFeel_V2::createDocumentWindowButton (int buttonType)
 - {
 -     Path shape;
 -     const float crossThickness = 0.25f;
 - 
 -     if (buttonType == DocumentWindow::closeButton)
 -     {
 -         shape.addLineSegment (Line<float> (0.0f, 0.0f, 1.0f, 1.0f), crossThickness * 1.4f);
 -         shape.addLineSegment (Line<float> (1.0f, 0.0f, 0.0f, 1.0f), crossThickness * 1.4f);
 - 
 -         return new GlassWindowButton ("close", Colour (0xffdd1100), shape, shape);
 -     }
 - 
 -     if (buttonType == DocumentWindow::minimiseButton)
 -     {
 -         shape.addLineSegment (Line<float> (0.0f, 0.5f, 1.0f, 0.5f), crossThickness);
 - 
 -         return new GlassWindowButton ("minimise", Colour (0xffaa8811), shape, shape);
 -     }
 - 
 -     if (buttonType == DocumentWindow::maximiseButton)
 -     {
 -         shape.addLineSegment (Line<float> (0.5f, 0.0f, 0.5f, 1.0f), crossThickness);
 -         shape.addLineSegment (Line<float> (0.0f, 0.5f, 1.0f, 0.5f), crossThickness);
 - 
 -         Path fullscreenShape;
 -         fullscreenShape.startNewSubPath (45.0f, 100.0f);
 -         fullscreenShape.lineTo (0.0f, 100.0f);
 -         fullscreenShape.lineTo (0.0f, 0.0f);
 -         fullscreenShape.lineTo (100.0f, 0.0f);
 -         fullscreenShape.lineTo (100.0f, 45.0f);
 -         fullscreenShape.addRectangle (45.0f, 45.0f, 100.0f, 100.0f);
 -         PathStrokeType (30.0f).createStrokedPath (fullscreenShape, fullscreenShape);
 - 
 -         return new GlassWindowButton ("maximise", Colour (0xff119911), shape, fullscreenShape);
 -     }
 - 
 -     jassertfalse;
 -     return nullptr;
 - }
 - 
 - void LookAndFeel_V2::positionDocumentWindowButtons (DocumentWindow&,
 -                                                     int titleBarX, int titleBarY,
 -                                                     int titleBarW, int titleBarH,
 -                                                     Button* minimiseButton,
 -                                                     Button* maximiseButton,
 -                                                     Button* closeButton,
 -                                                     bool positionTitleBarButtonsOnLeft)
 - {
 -     const int buttonW = titleBarH - titleBarH / 8;
 - 
 -     int x = positionTitleBarButtonsOnLeft ? titleBarX + 4
 -                                           : titleBarX + titleBarW - buttonW - buttonW / 4;
 - 
 -     if (closeButton != nullptr)
 -     {
 -         closeButton->setBounds (x, titleBarY, buttonW, titleBarH);
 -         x += positionTitleBarButtonsOnLeft ? buttonW : -(buttonW + buttonW / 4);
 -     }
 - 
 -     if (positionTitleBarButtonsOnLeft)
 -         std::swap (minimiseButton, maximiseButton);
 - 
 -     if (maximiseButton != nullptr)
 -     {
 -         maximiseButton->setBounds (x, titleBarY, buttonW, titleBarH);
 -         x += positionTitleBarButtonsOnLeft ? buttonW : -buttonW;
 -     }
 - 
 -     if (minimiseButton != nullptr)
 -         minimiseButton->setBounds (x, titleBarY, buttonW, titleBarH);
 - }
 - 
 - int LookAndFeel_V2::getDefaultMenuBarHeight()
 - {
 -     return 24;
 - }
 - 
 - //==============================================================================
 - DropShadower* LookAndFeel_V2::createDropShadowerForComponent (Component*)
 - {
 -     return new DropShadower (DropShadow (Colours::black.withAlpha (0.4f), 10, Point<int> (0, 2)));
 - }
 - 
 - //==============================================================================
 - void LookAndFeel_V2::drawStretchableLayoutResizerBar (Graphics& g, int w, int h,
 -                                                       bool /*isVerticalBar*/,
 -                                                       bool isMouseOver,
 -                                                       bool isMouseDragging)
 - {
 -     auto alpha = 0.5f;
 - 
 -     if (isMouseOver || isMouseDragging)
 -     {
 -         g.fillAll (Colour (0x190000ff));
 -         alpha = 1.0f;
 -     }
 - 
 -     auto cx = (float) w * 0.5f;
 -     auto cy = (float) h * 0.5f;
 -     auto cr = (float) jmin (w, h) * 0.4f;
 - 
 -     g.setGradientFill (ColourGradient (Colours::white.withAlpha (alpha), cx + cr * 0.1f, cy + cr,
 -                                        Colours::black.withAlpha (alpha), cx, cy - cr * 4.0f,
 -                                        true));
 - 
 -     g.fillEllipse (cx - cr, cy - cr, cr * 2.0f, cr * 2.0f);
 - }
 - 
 - //==============================================================================
 - void LookAndFeel_V2::drawGroupComponentOutline (Graphics& g, int width, int height,
 -                                                 const String& text, const Justification& position,
 -                                                 GroupComponent& group)
 - {
 -     const float textH = 15.0f;
 -     const float indent = 3.0f;
 -     const float textEdgeGap = 4.0f;
 -     auto cs = 5.0f;
 - 
 -     Font f (textH);
 - 
 -     Path p;
 -     auto x = indent;
 -     auto y = f.getAscent() - 3.0f;
 -     auto w = jmax (0.0f, (float) width - x * 2.0f);
 -     auto h = jmax (0.0f, (float) height - y  - indent);
 -     cs = jmin (cs, w * 0.5f, h * 0.5f);
 -     auto cs2 = 2.0f * cs;
 - 
 -     auto textW = text.isEmpty() ? 0
 -                                 : jlimit (0.0f,
 -                                           jmax (0.0f, w - cs2 - textEdgeGap * 2),
 -                                           (float) f.getStringWidth (text) + textEdgeGap * 2.0f);
 -     auto textX = cs + textEdgeGap;
 - 
 -     if (position.testFlags (Justification::horizontallyCentred))
 -         textX = cs + (w - cs2 - textW) * 0.5f;
 -     else if (position.testFlags (Justification::right))
 -         textX = w - cs - textW - textEdgeGap;
 - 
 -     p.startNewSubPath (x + textX + textW, y);
 -     p.lineTo (x + w - cs, y);
 - 
 -     p.addArc (x + w - cs2, y, cs2, cs2, 0, MathConstants<float>::halfPi);
 -     p.lineTo (x + w, y + h - cs);
 - 
 -     p.addArc (x + w - cs2, y + h - cs2, cs2, cs2, MathConstants<float>::halfPi, MathConstants<float>::pi);
 -     p.lineTo (x + cs, y + h);
 - 
 -     p.addArc (x, y + h - cs2, cs2, cs2, MathConstants<float>::pi, MathConstants<float>::pi * 1.5f);
 -     p.lineTo (x, y + cs);
 - 
 -     p.addArc (x, y, cs2, cs2, MathConstants<float>::pi * 1.5f, MathConstants<float>::twoPi);
 -     p.lineTo (x + textX, y);
 - 
 -     auto alpha = group.isEnabled() ? 1.0f : 0.5f;
 - 
 -     g.setColour (group.findColour (GroupComponent::outlineColourId)
 -                     .withMultipliedAlpha (alpha));
 - 
 -     g.strokePath (p, PathStrokeType (2.0f));
 - 
 -     g.setColour (group.findColour (GroupComponent::textColourId)
 -                     .withMultipliedAlpha (alpha));
 -     g.setFont (f);
 -     g.drawText (text,
 -                 roundToInt (x + textX), 0,
 -                 roundToInt (textW),
 -                 roundToInt (textH),
 -                 Justification::centred, true);
 - }
 - 
 - //==============================================================================
 - int LookAndFeel_V2::getTabButtonOverlap (int tabDepth)
 - {
 -     return 1 + tabDepth / 3;
 - }
 - 
 - int LookAndFeel_V2::getTabButtonSpaceAroundImage()
 - {
 -     return 4;
 - }
 - 
 - int LookAndFeel_V2::getTabButtonBestWidth (TabBarButton& button, int tabDepth)
 - {
 -     int width = Font ((float) tabDepth * 0.6f).getStringWidth (button.getButtonText().trim())
 -                    + getTabButtonOverlap (tabDepth) * 2;
 - 
 -     if (auto* extraComponent = button.getExtraComponent())
 -         width += button.getTabbedButtonBar().isVertical() ? extraComponent->getHeight()
 -                                                           : extraComponent->getWidth();
 - 
 -     return jlimit (tabDepth * 2, tabDepth * 8, width);
 - }
 - 
 - Rectangle<int> LookAndFeel_V2::getTabButtonExtraComponentBounds (const TabBarButton& button, Rectangle<int>& textArea, Component& comp)
 - {
 -     Rectangle<int> extraComp;
 - 
 -     auto orientation = button.getTabbedButtonBar().getOrientation();
 - 
 -     if (button.getExtraComponentPlacement() == TabBarButton::beforeText)
 -     {
 -         switch (orientation)
 -         {
 -             case TabbedButtonBar::TabsAtBottom:
 -             case TabbedButtonBar::TabsAtTop:     extraComp = textArea.removeFromLeft   (comp.getWidth()); break;
 -             case TabbedButtonBar::TabsAtLeft:    extraComp = textArea.removeFromBottom (comp.getHeight()); break;
 -             case TabbedButtonBar::TabsAtRight:   extraComp = textArea.removeFromTop    (comp.getHeight()); break;
 -             default:                             jassertfalse; break;
 -         }
 -     }
 -     else
 -     {
 -         switch (orientation)
 -         {
 -             case TabbedButtonBar::TabsAtBottom:
 -             case TabbedButtonBar::TabsAtTop:     extraComp = textArea.removeFromRight  (comp.getWidth()); break;
 -             case TabbedButtonBar::TabsAtLeft:    extraComp = textArea.removeFromTop    (comp.getHeight()); break;
 -             case TabbedButtonBar::TabsAtRight:   extraComp = textArea.removeFromBottom (comp.getHeight()); break;
 -             default:                             jassertfalse; break;
 -         }
 -     }
 - 
 -     return extraComp;
 - }
 - 
 - void LookAndFeel_V2::createTabButtonShape (TabBarButton& button, Path& p, bool /*isMouseOver*/, bool /*isMouseDown*/)
 - {
 -     auto activeArea = button.getActiveArea();
 -     auto w = (float) activeArea.getWidth();
 -     auto h = (float) activeArea.getHeight();
 - 
 -     auto length = w;
 -     auto depth = h;
 - 
 -     if (button.getTabbedButtonBar().isVertical())
 -         std::swap (length, depth);
 - 
 -     const float indent = (float) getTabButtonOverlap ((int) depth);
 -     const float overhang = 4.0f;
 - 
 -     switch (button.getTabbedButtonBar().getOrientation())
 -     {
 -         case TabbedButtonBar::TabsAtLeft:
 -             p.startNewSubPath (w, 0.0f);
 -             p.lineTo (0.0f, indent);
 -             p.lineTo (0.0f, h - indent);
 -             p.lineTo (w, h);
 -             p.lineTo (w + overhang, h + overhang);
 -             p.lineTo (w + overhang, -overhang);
 -             break;
 - 
 -         case TabbedButtonBar::TabsAtRight:
 -             p.startNewSubPath (0.0f, 0.0f);
 -             p.lineTo (w, indent);
 -             p.lineTo (w, h - indent);
 -             p.lineTo (0.0f, h);
 -             p.lineTo (-overhang, h + overhang);
 -             p.lineTo (-overhang, -overhang);
 -             break;
 - 
 -         case TabbedButtonBar::TabsAtBottom:
 -             p.startNewSubPath (0.0f, 0.0f);
 -             p.lineTo (indent, h);
 -             p.lineTo (w - indent, h);
 -             p.lineTo (w, 0.0f);
 -             p.lineTo (w + overhang, -overhang);
 -             p.lineTo (-overhang, -overhang);
 -             break;
 - 
 -         case TabbedButtonBar::TabsAtTop:
 -         default:
 -             p.startNewSubPath (0.0f, h);
 -             p.lineTo (indent, 0.0f);
 -             p.lineTo (w - indent, 0.0f);
 -             p.lineTo (w, h);
 -             p.lineTo (w + overhang, h + overhang);
 -             p.lineTo (-overhang, h + overhang);
 -             break;
 -     }
 - 
 -     p.closeSubPath();
 - 
 -     p = p.createPathWithRoundedCorners (3.0f);
 - }
 - 
 - void LookAndFeel_V2::fillTabButtonShape (TabBarButton& button, Graphics& g, const Path& path,
 -                                          bool /*isMouseOver*/, bool /*isMouseDown*/)
 - {
 -     auto tabBackground = button.getTabBackgroundColour();
 -     const bool isFrontTab = button.isFrontTab();
 - 
 -     g.setColour (isFrontTab ? tabBackground
 -                             : tabBackground.withMultipliedAlpha (0.9f));
 - 
 -     g.fillPath (path);
 - 
 -     g.setColour (button.findColour (isFrontTab ? TabbedButtonBar::frontOutlineColourId
 -                                                : TabbedButtonBar::tabOutlineColourId, false)
 -                     .withMultipliedAlpha (button.isEnabled() ? 1.0f : 0.5f));
 - 
 -     g.strokePath (path, PathStrokeType (isFrontTab ? 1.0f : 0.5f));
 - }
 - 
 - Font LookAndFeel_V2::getTabButtonFont (TabBarButton&, float height)
 - {
 -     return { height * 0.6f };
 - }
 - 
 - void LookAndFeel_V2::drawTabButtonText (TabBarButton& button, Graphics& g, bool isMouseOver, bool isMouseDown)
 - {
 -     auto area = button.getTextArea().toFloat();
 - 
 -     auto length = area.getWidth();
 -     auto depth  = area.getHeight();
 - 
 -     if (button.getTabbedButtonBar().isVertical())
 -         std::swap (length, depth);
 - 
 -     Font font (getTabButtonFont (button, depth));
 -     font.setUnderline (button.hasKeyboardFocus (false));
 - 
 -     AffineTransform t;
 - 
 -     switch (button.getTabbedButtonBar().getOrientation())
 -     {
 -         case TabbedButtonBar::TabsAtLeft:   t = t.rotated (MathConstants<float>::pi * -0.5f).translated (area.getX(), area.getBottom()); break;
 -         case TabbedButtonBar::TabsAtRight:  t = t.rotated (MathConstants<float>::pi *  0.5f).translated (area.getRight(), area.getY()); break;
 -         case TabbedButtonBar::TabsAtTop:
 -         case TabbedButtonBar::TabsAtBottom: t = t.translated (area.getX(), area.getY()); break;
 -         default:                            jassertfalse; break;
 -     }
 - 
 -     Colour col;
 - 
 -     if (button.isFrontTab() && (button.isColourSpecified (TabbedButtonBar::frontTextColourId)
 -                                     || isColourSpecified (TabbedButtonBar::frontTextColourId)))
 -         col = findColour (TabbedButtonBar::frontTextColourId);
 -     else if (button.isColourSpecified (TabbedButtonBar::tabTextColourId)
 -                  || isColourSpecified (TabbedButtonBar::tabTextColourId))
 -         col = findColour (TabbedButtonBar::tabTextColourId);
 -     else
 -         col = button.getTabBackgroundColour().contrasting();
 - 
 -     auto alpha = button.isEnabled() ? ((isMouseOver || isMouseDown) ? 1.0f : 0.8f) : 0.3f;
 - 
 -     g.setColour (col.withMultipliedAlpha (alpha));
 -     g.setFont (font);
 -     g.addTransform (t);
 - 
 -     g.drawFittedText (button.getButtonText().trim(),
 -                       0, 0, (int) length, (int) depth,
 -                       Justification::centred,
 -                       jmax (1, ((int) depth) / 12));
 - }
 - 
 - void LookAndFeel_V2::drawTabButton (TabBarButton& button, Graphics& g, bool isMouseOver, bool isMouseDown)
 - {
 -     Path tabShape;
 -     createTabButtonShape (button, tabShape, isMouseOver, isMouseDown);
 - 
 -     auto activeArea = button.getActiveArea();
 -     tabShape.applyTransform (AffineTransform::translation ((float) activeArea.getX(),
 -                                                            (float) activeArea.getY()));
 - 
 -     DropShadow (Colours::black.withAlpha (0.5f), 2, Point<int> (0, 1)).drawForPath (g, tabShape);
 - 
 -     fillTabButtonShape (button, g, tabShape, isMouseOver, isMouseDown);
 -     drawTabButtonText (button, g, isMouseOver, isMouseDown);
 - }
 - 
 - void LookAndFeel_V2::drawTabbedButtonBarBackground (TabbedButtonBar&, Graphics&) {}
 - 
 - void LookAndFeel_V2::drawTabAreaBehindFrontButton (TabbedButtonBar& bar, Graphics& g, const int w, const int h)
 - {
 -     auto shadowSize = 0.2f;
 - 
 -     Rectangle<int> shadowRect, line;
 -     ColourGradient gradient (Colours::black.withAlpha (bar.isEnabled() ? 0.25f : 0.15f), 0, 0,
 -                              Colours::transparentBlack, 0, 0, false);
 - 
 -     switch (bar.getOrientation())
 -     {
 -         case TabbedButtonBar::TabsAtLeft:
 -             gradient.point1.x = (float) w;
 -             gradient.point2.x = (float) w * (1.0f - shadowSize);
 -             shadowRect.setBounds ((int) gradient.point2.x, 0, w - (int) gradient.point2.x, h);
 -             line.setBounds (w - 1, 0, 1, h);
 -             break;
 - 
 -         case TabbedButtonBar::TabsAtRight:
 -             gradient.point2.x = (float) w * shadowSize;
 -             shadowRect.setBounds (0, 0, (int) gradient.point2.x, h);
 -             line.setBounds (0, 0, 1, h);
 -             break;
 - 
 -         case TabbedButtonBar::TabsAtTop:
 -             gradient.point1.y = (float) h;
 -             gradient.point2.y = (float) h * (1.0f - shadowSize);
 -             shadowRect.setBounds (0, (int) gradient.point2.y, w, h - (int) gradient.point2.y);
 -             line.setBounds (0, h - 1, w, 1);
 -             break;
 - 
 -         case TabbedButtonBar::TabsAtBottom:
 -             gradient.point2.y = (float) h * shadowSize;
 -             shadowRect.setBounds (0, 0, w, (int) gradient.point2.y);
 -             line.setBounds (0, 0, w, 1);
 -             break;
 - 
 -         default: break;
 -     }
 - 
 -     g.setGradientFill (gradient);
 -     g.fillRect (shadowRect.expanded (2, 2));
 - 
 -     g.setColour (Colour (0x80000000));
 -     g.fillRect (line);
 - }
 - 
 - Button* LookAndFeel_V2::createTabBarExtrasButton()
 - {
 -     auto thickness = 7.0f;
 -     auto indent = 22.0f;
 - 
 -     Path p;
 -     p.addEllipse (-10.0f, -10.0f, 120.0f, 120.0f);
 - 
 -     DrawablePath ellipse;
 -     ellipse.setPath (p);
 -     ellipse.setFill (Colour (0x99ffffff));
 - 
 -     p.clear();
 -     p.addEllipse (0.0f, 0.0f, 100.0f, 100.0f);
 -     p.addRectangle (indent, 50.0f - thickness, 100.0f - indent * 2.0f, thickness * 2.0f);
 -     p.addRectangle (50.0f - thickness, indent, thickness * 2.0f, 50.0f - indent - thickness);
 -     p.addRectangle (50.0f - thickness, 50.0f + thickness, thickness * 2.0f, 50.0f - indent - thickness);
 -     p.setUsingNonZeroWinding (false);
 - 
 -     DrawablePath dp;
 -     dp.setPath (p);
 -     dp.setFill (Colour (0x59000000));
 - 
 -     DrawableComposite normalImage;
 -     normalImage.addAndMakeVisible (ellipse.createCopy().release());
 -     normalImage.addAndMakeVisible (dp.createCopy().release());
 - 
 -     dp.setFill (Colour (0xcc000000));
 - 
 -     DrawableComposite overImage;
 -     overImage.addAndMakeVisible (ellipse.createCopy().release());
 -     overImage.addAndMakeVisible (dp.createCopy().release());
 - 
 -     auto db = new DrawableButton ("tabs", DrawableButton::ImageFitted);
 -     db->setImages (&normalImage, &overImage, nullptr);
 -     return db;
 - }
 - 
 - 
 - //==============================================================================
 - void LookAndFeel_V2::drawTableHeaderBackground (Graphics& g, TableHeaderComponent& header)
 - {
 -     g.fillAll (Colours::white);
 - 
 -     auto area = header.getLocalBounds();
 -     area.removeFromTop (area.getHeight() / 2);
 - 
 -     auto backgroundColour = header.findColour (TableHeaderComponent::backgroundColourId);
 - 
 -     g.setGradientFill (ColourGradient (backgroundColour,
 -                                        0.0f, (float) area.getY(),
 -                                        backgroundColour.withMultipliedSaturation (.5f),
 -                                        0.0f, (float) area.getBottom(),
 -                                        false));
 -     g.fillRect (area);
 - 
 -     g.setColour (header.findColour (TableHeaderComponent::outlineColourId));
 -     g.fillRect (area.removeFromBottom (1));
 - 
 -     for (int i = header.getNumColumns (true); --i >= 0;)
 -         g.fillRect (header.getColumnPosition (i).removeFromRight (1));
 - }
 - 
 - void LookAndFeel_V2::drawTableHeaderColumn (Graphics& g, TableHeaderComponent& header,
 -                                             const String& columnName, int /*columnId*/,
 -                                             int width, int height, bool isMouseOver, bool isMouseDown,
 -                                             int columnFlags)
 - {
 -     auto highlightColour = header.findColour (TableHeaderComponent::highlightColourId);
 - 
 -     if (isMouseDown)
 -         g.fillAll (highlightColour);
 -     else if (isMouseOver)
 -         g.fillAll (highlightColour.withMultipliedAlpha (0.625f));
 - 
 -     Rectangle<int> area (width, height);
 -     area.reduce (4, 0);
 - 
 -     if ((columnFlags & (TableHeaderComponent::sortedForwards | TableHeaderComponent::sortedBackwards)) != 0)
 -     {
 -         Path sortArrow;
 -         sortArrow.addTriangle (0.0f, 0.0f,
 -                                0.5f, (columnFlags & TableHeaderComponent::sortedForwards) != 0 ? -0.8f : 0.8f,
 -                                1.0f, 0.0f);
 - 
 -         g.setColour (Colour (0x99000000));
 -         g.fillPath (sortArrow, sortArrow.getTransformToScaleToFit (area.removeFromRight (height / 2).reduced (2).toFloat(), true));
 -     }
 - 
 -     g.setColour (header.findColour (TableHeaderComponent::textColourId));
 -     g.setFont (Font ((float) height * 0.5f, Font::bold));
 -     g.drawFittedText (columnName, area, Justification::centredLeft, 1);
 - }
 - 
 - //==============================================================================
 - void LookAndFeel_V2::drawLasso (Graphics& g, Component& lassoComp)
 - {
 -     const int outlineThickness = 1;
 - 
 -     g.fillAll (lassoComp.findColour (0x1000440 /*lassoFillColourId*/));
 - 
 -     g.setColour (lassoComp.findColour (0x1000441 /*lassoOutlineColourId*/));
 -     g.drawRect (lassoComp.getLocalBounds(), outlineThickness);
 - }
 - 
 - //==============================================================================
 - void LookAndFeel_V2::paintToolbarBackground (Graphics& g, int w, int h, Toolbar& toolbar)
 - {
 -     auto background = toolbar.findColour (Toolbar::backgroundColourId);
 - 
 -     g.setGradientFill (ColourGradient (background, 0.0f, 0.0f,
 -                                        background.darker (0.1f),
 -                                        toolbar.isVertical() ? (float) w - 1.0f : 0.0f,
 -                                        toolbar.isVertical() ? 0.0f : (float) h - 1.0f,
 -                                        false));
 -     g.fillAll();
 - }
 - 
 - Button* LookAndFeel_V2::createToolbarMissingItemsButton (Toolbar& /*toolbar*/)
 - {
 -     return createTabBarExtrasButton();
 - }
 - 
 - void LookAndFeel_V2::paintToolbarButtonBackground (Graphics& g, int /*width*/, int /*height*/,
 -                                                    bool isMouseOver, bool isMouseDown,
 -                                                    ToolbarItemComponent& component)
 - {
 -     if (isMouseDown)
 -         g.fillAll (component.findColour (Toolbar::buttonMouseDownBackgroundColourId, true));
 -     else if (isMouseOver)
 -         g.fillAll (component.findColour (Toolbar::buttonMouseOverBackgroundColourId, true));
 - }
 - 
 - void LookAndFeel_V2::paintToolbarButtonLabel (Graphics& g, int x, int y, int width, int height,
 -                                               const String& text, ToolbarItemComponent& component)
 - {
 -     g.setColour (component.findColour (Toolbar::labelTextColourId, true)
 -                     .withAlpha (component.isEnabled() ? 1.0f : 0.25f));
 - 
 -     auto fontHeight = jmin (14.0f, (float) height * 0.85f);
 -     g.setFont (fontHeight);
 - 
 -     g.drawFittedText (text,
 -                       x, y, width, height,
 -                       Justification::centred,
 -                       jmax (1, height / (int) fontHeight));
 - }
 - 
 - //==============================================================================
 - void LookAndFeel_V2::drawPropertyPanelSectionHeader (Graphics& g, const String& name,
 -                                                      bool isOpen, int width, int height)
 - {
 -     auto buttonSize = (float) height * 0.75f;
 -     auto buttonIndent = ((float) height - buttonSize) * 0.5f;
 - 
 -     drawTreeviewPlusMinusBox (g, Rectangle<float> (buttonIndent, buttonIndent, buttonSize, buttonSize), Colours::white, isOpen, false);
 - 
 -     auto textX = (int) (buttonIndent * 2.0f + buttonSize + 2.0f);
 - 
 -     g.setColour (Colours::black);
 -     g.setFont (Font ((float) height * 0.7f, Font::bold));
 -     g.drawText (name, textX, 0, width - textX - 4, height, Justification::centredLeft, true);
 - }
 - 
 - void LookAndFeel_V2::drawPropertyComponentBackground (Graphics& g, int width, int height, PropertyComponent& component)
 - {
 -     g.setColour (component.findColour (PropertyComponent::backgroundColourId));
 -     g.fillRect (0, 0, width, height - 1);
 - }
 - 
 - void LookAndFeel_V2::drawPropertyComponentLabel (Graphics& g, int, int height, PropertyComponent& component)
 - {
 -     g.setColour (component.findColour (PropertyComponent::labelTextColourId)
 -                     .withMultipliedAlpha (component.isEnabled() ? 1.0f : 0.6f));
 - 
 -     g.setFont ((float) jmin (height, 24) * 0.65f);
 - 
 -     auto r = getPropertyComponentContentPosition (component);
 - 
 -     g.drawFittedText (component.getName(),
 -                       3, r.getY(), r.getX() - 5, r.getHeight(),
 -                       Justification::centredLeft, 2);
 - }
 - 
 - Rectangle<int> LookAndFeel_V2::getPropertyComponentContentPosition (PropertyComponent& component)
 - {
 -     const int textW = jmin (200, component.getWidth() / 3);
 -     return Rectangle<int> (textW, 1, component.getWidth() - textW - 1, component.getHeight() - 3);
 - }
 - 
 - int LookAndFeel_V2::getPropertyPanelSectionHeaderHeight (const String& sectionTitle)
 - {
 -     return sectionTitle.isEmpty() ? 0 : 22;
 - }
 - 
 - //==============================================================================
 - void LookAndFeel_V2::drawCallOutBoxBackground (CallOutBox& box, Graphics& g,
 -                                                const Path& path, Image& cachedImage)
 - {
 -     if (cachedImage.isNull())
 -     {
 -         cachedImage = Image (Image::ARGB, box.getWidth(), box.getHeight(), true);
 -         Graphics g2 (cachedImage);
 - 
 -         DropShadow (Colours::black.withAlpha (0.7f), 8, Point<int> (0, 2)).drawForPath (g2, path);
 -     }
 - 
 -     g.setColour (Colours::black);
 -     g.drawImageAt (cachedImage, 0, 0);
 - 
 -     g.setColour (Colour::greyLevel (0.23f).withAlpha (0.9f));
 -     g.fillPath (path);
 - 
 -     g.setColour (Colours::white.withAlpha (0.8f));
 -     g.strokePath (path, PathStrokeType (2.0f));
 - }
 - 
 - int LookAndFeel_V2::getCallOutBoxBorderSize (const CallOutBox&)
 - {
 -     return 20;
 - }
 - 
 - float LookAndFeel_V2::getCallOutBoxCornerSize (const CallOutBox&)
 - {
 -     return 9.0f;
 - }
 - 
 - //==============================================================================
 - AttributedString LookAndFeel_V2::createFileChooserHeaderText (const String& title,
 -                                                            const String& instructions)
 - {
 -     AttributedString s;
 -     s.setJustification (Justification::centred);
 - 
 -     auto colour = findColour (FileChooserDialogBox::titleTextColourId);
 -     s.append (title + "\n\n", Font (17.0f, Font::bold), colour);
 -     s.append (instructions, Font (14.0f), colour);
 - 
 -     return s;
 - }
 - 
 - void LookAndFeel_V2::drawFileBrowserRow (Graphics& g, int width, int height,
 -                                          const File&, const String& filename, Image* icon,
 -                                          const String& fileSizeDescription,
 -                                          const String& fileTimeDescription,
 -                                          bool isDirectory, bool isItemSelected,
 -                                          int /*itemIndex*/, DirectoryContentsDisplayComponent& dcc)
 - {
 -     auto fileListComp = dynamic_cast<Component*> (&dcc);
 - 
 -     if (isItemSelected)
 -         g.fillAll (fileListComp != nullptr ? fileListComp->findColour (DirectoryContentsDisplayComponent::highlightColourId)
 -                                            : findColour (DirectoryContentsDisplayComponent::highlightColourId));
 - 
 -     const int x = 32;
 -     g.setColour (Colours::black);
 - 
 -     if (icon != nullptr && icon->isValid())
 -     {
 -         g.drawImageWithin (*icon, 2, 2, x - 4, height - 4,
 -                            RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize,
 -                            false);
 -     }
 -     else
 -     {
 -         if (auto* d = isDirectory ? getDefaultFolderImage()
 -                                   : getDefaultDocumentFileImage())
 -             d->drawWithin (g, Rectangle<float> (2.0f, 2.0f, x - 4.0f, (float) height - 4.0f),
 -                            RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize, 1.0f);
 -     }
 - 
 -     if (isItemSelected)
 -         g.setColour (fileListComp != nullptr ? fileListComp->findColour (DirectoryContentsDisplayComponent::highlightedTextColourId)
 -                                              : findColour (DirectoryContentsDisplayComponent::highlightedTextColourId));
 -     else
 -         g.setColour (fileListComp != nullptr ? fileListComp->findColour (DirectoryContentsDisplayComponent::textColourId)
 -                                              : findColour (DirectoryContentsDisplayComponent::textColourId));
 - 
 -     g.setFont ((float) height * 0.7f);
 - 
 -     if (width > 450 && ! isDirectory)
 -     {
 -         auto sizeX = roundToInt ((float) width * 0.7f);
 -         auto dateX = roundToInt ((float) width * 0.8f);
 - 
 -         g.drawFittedText (filename,
 -                           x, 0, sizeX - x, height,
 -                           Justification::centredLeft, 1);
 - 
 -         g.setFont ((float) height * 0.5f);
 -         g.setColour (Colours::darkgrey);
 - 
 -         if (! isDirectory)
 -         {
 -             g.drawFittedText (fileSizeDescription,
 -                               sizeX, 0, dateX - sizeX - 8, height,
 -                               Justification::centredRight, 1);
 - 
 -             g.drawFittedText (fileTimeDescription,
 -                               dateX, 0, width - 8 - dateX, height,
 -                               Justification::centredRight, 1);
 -         }
 -     }
 -     else
 -     {
 -         g.drawFittedText (filename,
 -                           x, 0, width - x, height,
 -                           Justification::centredLeft, 1);
 - 
 -     }
 - }
 - 
 - Button* LookAndFeel_V2::createFileBrowserGoUpButton()
 - {
 -     auto goUpButton = new DrawableButton ("up", DrawableButton::ImageOnButtonBackground);
 - 
 -     Path arrowPath;
 -     arrowPath.addArrow ({ 50.0f, 100.0f, 50.0f, 0.0f }, 40.0f, 100.0f, 50.0f);
 - 
 -     DrawablePath arrowImage;
 -     arrowImage.setFill (Colours::black.withAlpha (0.4f));
 -     arrowImage.setPath (arrowPath);
 - 
 -     goUpButton->setImages (&arrowImage);
 - 
 -     return goUpButton;
 - }
 - 
 - void LookAndFeel_V2::layoutFileBrowserComponent (FileBrowserComponent& browserComp,
 -                                                  DirectoryContentsDisplayComponent* fileListComponent,
 -                                                  FilePreviewComponent* previewComp,
 -                                                  ComboBox* currentPathBox,
 -                                                  TextEditor* filenameBox,
 -                                                  Button* goUpButton)
 - {
 -     const int x = 8;
 -     auto w = browserComp.getWidth() - x - x;
 - 
 -     if (previewComp != nullptr)
 -     {
 -         auto previewWidth = w / 3;
 -         previewComp->setBounds (x + w - previewWidth, 0, previewWidth, browserComp.getHeight());
 - 
 -         w -= previewWidth + 4;
 -     }
 - 
 -     int y = 4;
 - 
 -     const int controlsHeight = 22;
 -     const int upButtonWidth = 50;
 -     auto bottomSectionHeight = controlsHeight + 8;
 - 
 -     currentPathBox->setBounds (x, y, w - upButtonWidth - 6, controlsHeight);
 -     goUpButton->setBounds (x + w - upButtonWidth, y, upButtonWidth, controlsHeight);
 - 
 -     y += controlsHeight + 4;
 - 
 -     if (auto listAsComp = dynamic_cast<Component*> (fileListComponent))
 -     {
 -         listAsComp->setBounds (x, y, w, browserComp.getHeight() - y - bottomSectionHeight);
 -         y = listAsComp->getBottom() + 4;
 -     }
 - 
 -     filenameBox->setBounds (x + 50, y, w - 50, controlsHeight);
 - }
 - 
 - //==============================================================================
 - static std::unique_ptr<Drawable> createDrawableFromSVG (const char* data)
 - {
 -     auto xml = parseXML (data);
 -     jassert (xml != nullptr);
 -     return Drawable::createFromSVG (*xml);
 - }
 - 
 - const Drawable* LookAndFeel_V2::getDefaultFolderImage()
 - {
 -     if (folderImage == nullptr)
 -         folderImage = createDrawableFromSVG (R"svgdata(
 - <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="706" height="532">
 -   <defs>
 -     <linearGradient id="a">
 -       <stop stop-color="#adf" offset="0"/>
 -       <stop stop-color="#ecfaff" offset="1"/>
 -     </linearGradient>
 -     <linearGradient id="b" x1=".6" x2="0" y1=".9" xlink:href="#a"/>
 -     <linearGradient id="c" x1=".6" x2=".1" y1=".9" y2=".3" xlink:href="#a"/>
 -   </defs>
 -   <g class="currentLayer">
 -     <path d="M112.1 104c-8.2 2.2-13.2 11.6-11.3 21l68.3 342.7c1.9 9.4 10.1 15.2 18.4 13l384.3-104.1c8.2-2.2 13.2-11.6 11.3-21l-48-266a15.8 15.8 0 0 0-18.4-12.8l-224.2 38s-20.3-41.3-28.3-39.3z" display="block" fill="url(#b)" stroke="#446c98" stroke-width="7"/>
 -     <path d="M608.6 136.8L235.2 208a22.7 22.7 0 0 0-16 19l-40.8 241c1.7 8.4 9.6 14.5 17.8 12.3l380-104c8-2.2 10.7-10.2 12.3-18.4l38-210.1c.4-15.4-10.4-11.8-18-11.1z" display="block" fill="url(#c)" opacity=".8" stroke="#446c98" stroke-width="7"/>
 -   </g>
 - </svg>
 - )svgdata");
 - 
 -     return folderImage.get();
 - }
 - 
 - const Drawable* LookAndFeel_V2::getDefaultDocumentFileImage()
 - {
 -     if (documentImage == nullptr)
 -         documentImage = createDrawableFromSVG (R"svgdata(
 - <svg version="1" viewBox="-10 -10 450 600" xmlns="http://www.w3.org/2000/svg">
 -   <path d="M17 0h290l120 132v426c0 10-8 19-17 19H17c-9 0-17-9-17-19V19C0 8 8 0 17 0z" fill="#e5e5e5" stroke="#888888" stroke-width="7"/>
 -   <path d="M427 132H324c-9 0-17-9-17-19V0l120 132z" fill="#ccc"/>
 - </svg>
 - )svgdata");
 - 
 -     return documentImage.get();
 - }
 - 
 - //==============================================================================
 - static Path createPathFromData (float height, const unsigned char* data, size_t size)
 - {
 -     Path p;
 -     p.loadPathFromData (data, size);
 -     p.scaleToFit (0, 0, height * 2.0f, height, true);
 -     return p;
 - }
 - 
 - Path LookAndFeel_V2::getTickShape (float height)
 - {
 -     static const unsigned char data[] =
 -     {
 -         109,0,224,168,68,0,0,119,67,108,0,224,172,68,0,128,146,67,113,0,192,148,68,0,0,219,67,0,96,110,68,0,224,56,68,113,0,64,51,68,0,32,130,68,0,64,20,68,0,224,
 -         162,68,108,0,128,3,68,0,128,168,68,113,0,128,221,67,0,192,175,68,0,0,207,67,0,32,179,68,113,0,0,201,67,0,224,173,68,0,0,181,67,0,224,161,68,108,0,128,168,67,
 -         0,128,154,68,113,0,128,141,67,0,192,138,68,0,128,108,67,0,64,131,68,113,0,0,62,67,0,128,119,68,0,0,5,67,0,128,114,68,113,0,0,102,67,0,192,88,68,0,128,155,
 -         67,0,192,88,68,113,0,0,190,67,0,192,88,68,0,128,232,67,0,224,131,68,108,0,128,246,67,0,192,139,68,113,0,64,33,68,0,128,87,68,0,0,93,68,0,224,26,68,113,0,
 -         96,140,68,0,128,188,67,0,224,168,68,0,0,119,67,99,101
 -     };
 - 
 -     return createPathFromData (height, data, sizeof (data));
 - }
 - 
 - Path LookAndFeel_V2::getCrossShape (float height)
 - {
 -     static const unsigned char data[] =
 -     {
 -         109,0,0,17,68,0,96,145,68,108,0,192,13,68,0,192,147,68,113,0,0,213,67,0,64,174,68,0,0,168,67,0,64,174,68,113,0,0,104,67,0,64,174,68,0,0,5,67,0,64,
 -         153,68,113,0,0,18,67,0,64,153,68,0,0,24,67,0,64,153,68,113,0,0,135,67,0,64,153,68,0,128,207,67,0,224,130,68,108,0,0,220,67,0,0,126,68,108,0,0,204,67,
 -         0,128,117,68,113,0,0,138,67,0,64,82,68,0,0,138,67,0,192,57,68,113,0,0,138,67,0,192,37,68,0,128,210,67,0,64,10,68,113,0,128,220,67,0,64,45,68,0,0,8,
 -         68,0,128,78,68,108,0,192,14,68,0,0,87,68,108,0,64,20,68,0,0,80,68,113,0,192,57,68,0,0,32,68,0,128,88,68,0,0,32,68,113,0,64,112,68,0,0,32,68,0,
 -         128,124,68,0,64,68,68,113,0,0,121,68,0,192,67,68,0,128,119,68,0,192,67,68,113,0,192,108,68,0,192,67,68,0,32,89,68,0,96,82,68,113,0,128,69,68,0,0,97,68,
 -         0,0,56,68,0,64,115,68,108,0,64,49,68,0,128,124,68,108,0,192,55,68,0,96,129,68,113,0,0,92,68,0,224,146,68,0,192,129,68,0,224,146,68,113,0,64,110,68,0,64,
 -         168,68,0,64,87,68,0,64,168,68,113,0,128,66,68,0,64,168,68,0,64,27,68,0,32,150,68,99,101
 -     };
 - 
 -     return createPathFromData (height, data, sizeof (data));
 - }
 - 
 - //==============================================================================
 - void LookAndFeel_V2::drawLevelMeter (Graphics& g, int width, int height, float level)
 - {
 -     g.setColour (Colours::white.withAlpha (0.7f));
 -     g.fillRoundedRectangle (0.0f, 0.0f, (float) width, (float) height, 3.0f);
 -     g.setColour (Colours::black.withAlpha (0.2f));
 -     g.drawRoundedRectangle (1.0f, 1.0f, (float) width - 2.0f, (float) height - 2.0f, 3.0f, 1.0f);
 - 
 -     const int totalBlocks = 7;
 -     const int numBlocks = roundToInt (totalBlocks * level);
 -     auto w = ((float) width - 6.0f) / (float) totalBlocks;
 - 
 -     for (int i = 0; i < totalBlocks; ++i)
 -     {
 -         if (i >= numBlocks)
 -             g.setColour (Colours::lightblue.withAlpha (0.6f));
 -         else
 -             g.setColour (i < totalBlocks - 1 ? Colours::blue.withAlpha (0.5f)
 -                                              : Colours::red);
 - 
 -         g.fillRoundedRectangle (3.0f + (float) i * w + w * 0.1f,
 -                                 3.0f,
 -                                 (float) w * 0.8f,
 -                                 (float) height - 6.0f,
 -                                 (float) w * 0.4f);
 -     }
 - }
 - 
 - //==============================================================================
 - void LookAndFeel_V2::drawKeymapChangeButton (Graphics& g, int width, int height, Button& button, const String& keyDescription)
 - {
 -     auto textColour = button.findColour (0x100ad01 /*KeyMappingEditorComponent::textColourId*/, true);
 - 
 -     if (keyDescription.isNotEmpty())
 -     {
 -         if (button.isEnabled())
 -         {
 -             auto alpha = button.isDown() ? 0.3f : (button.isOver() ? 0.15f : 0.08f);
 -             g.fillAll (textColour.withAlpha (alpha));
 - 
 -             g.setOpacity (0.3f);
 -             drawBevel (g, 0, 0, width, height, 2);
 -         }
 - 
 -         g.setColour (textColour);
 -         g.setFont ((float) height * 0.6f);
 -         g.drawFittedText (keyDescription,
 -                           3, 0, width - 6, height,
 -                           Justification::centred, 1);
 -     }
 -     else
 -     {
 -         const float thickness = 7.0f;
 -         const float indent = 22.0f;
 - 
 -         Path p;
 -         p.addEllipse (0.0f, 0.0f, 100.0f, 100.0f);
 -         p.addRectangle (indent, 50.0f - thickness, 100.0f - indent * 2.0f, thickness * 2.0f);
 -         p.addRectangle (50.0f - thickness, indent, thickness * 2.0f, 50.0f - indent - thickness);
 -         p.addRectangle (50.0f - thickness, 50.0f + thickness, thickness * 2.0f, 50.0f - indent - thickness);
 -         p.setUsingNonZeroWinding (false);
 - 
 -         g.setColour (textColour.withAlpha (button.isDown() ? 0.7f : (button.isOver() ? 0.5f : 0.3f)));
 -         g.fillPath (p, p.getTransformToScaleToFit (2.0f, 2.0f, (float) width - 4.0f, (float) height - 4.0f, true));
 -     }
 - 
 -     if (button.hasKeyboardFocus (false))
 -     {
 -         g.setColour (textColour.withAlpha (0.4f));
 -         g.drawRect (0, 0, width, height);
 -     }
 - }
 - 
 - //==============================================================================
 - Font LookAndFeel_V2::getSidePanelTitleFont (SidePanel&)
 - {
 -     return Font (18.0f);
 - }
 - 
 - Justification LookAndFeel_V2::getSidePanelTitleJustification (SidePanel& panel)
 - {
 -     return panel.isPanelOnLeft() ? Justification::centredRight
 -                                  : Justification::centredLeft;
 - }
 - 
 - Path LookAndFeel_V2::getSidePanelDismissButtonShape (SidePanel& panel)
 - {
 -     return getCrossShape ((float) panel.getTitleBarHeight());
 - }
 - 
 - //==============================================================================
 - void LookAndFeel_V2::drawBevel (Graphics& g, const int x, const int y, const int width, const int height,
 -                                 const int bevelThickness, const Colour& topLeftColour, const Colour& bottomRightColour,
 -                                 const bool useGradient, const bool sharpEdgeOnOutside)
 - {
 -     if (g.clipRegionIntersects (Rectangle<int> (x, y, width, height)))
 -     {
 -         auto& context = g.getInternalContext();
 -         Graphics::ScopedSaveState ss (g);
 - 
 -         for (int i = bevelThickness; --i >= 0;)
 -         {
 -             const float op = useGradient ? (float) (sharpEdgeOnOutside ? bevelThickness - i : i) / (float) bevelThickness
 -                                          : 1.0f;
 - 
 -             context.setFill (topLeftColour.withMultipliedAlpha (op));
 -             context.fillRect (Rectangle<int> (x + i, y + i, width - i * 2, 1), false);
 -             context.setFill (topLeftColour.withMultipliedAlpha (op * 0.75f));
 -             context.fillRect (Rectangle<int> (x + i, y + i + 1, 1, height - i * 2 - 2), false);
 -             context.setFill (bottomRightColour.withMultipliedAlpha (op));
 -             context.fillRect (Rectangle<int> (x + i, y + height - i - 1, width - i * 2, 1), false);
 -             context.setFill (bottomRightColour.withMultipliedAlpha (op  * 0.75f));
 -             context.fillRect (Rectangle<int> (x + width - i - 1, y + i + 1, 1, height - i * 2 - 2), false);
 -         }
 -     }
 - }
 - 
 - //==============================================================================
 - void LookAndFeel_V2::drawShinyButtonShape (Graphics& g, float x, float y, float w, float h,
 -                                            float maxCornerSize, const Colour& baseColour, float strokeWidth,
 -                                            bool flatOnLeft, bool flatOnRight, bool flatOnTop, bool flatOnBottom) noexcept
 - {
 -     if (w <= strokeWidth * 1.1f || h <= strokeWidth * 1.1f)
 -         return;
 - 
 -     auto cs = jmin (maxCornerSize, w * 0.5f, h * 0.5f);
 - 
 -     Path outline;
 -     outline.addRoundedRectangle (x, y, w, h, cs, cs,
 -                                  ! (flatOnLeft  || flatOnTop),
 -                                  ! (flatOnRight || flatOnTop),
 -                                  ! (flatOnLeft  || flatOnBottom),
 -                                  ! (flatOnRight || flatOnBottom));
 - 
 -     ColourGradient cg (baseColour, 0.0f, y,
 -                        baseColour.overlaidWith (Colour (0x070000ff)), 0.0f, y + h,
 -                        false);
 - 
 -     cg.addColour (0.5,  baseColour.overlaidWith (Colour (0x33ffffff)));
 -     cg.addColour (0.51, baseColour.overlaidWith (Colour (0x110000ff)));
 - 
 -     g.setGradientFill (cg);
 -     g.fillPath (outline);
 - 
 -     g.setColour (Colour (0x80000000));
 -     g.strokePath (outline, PathStrokeType (strokeWidth));
 - }
 - 
 - //==============================================================================
 - void LookAndFeel_V2::drawGlassSphere (Graphics& g, const float x, const float y,
 -                                       const float diameter, const Colour& colour,
 -                                       const float outlineThickness) noexcept
 - {
 -     if (diameter <= outlineThickness)
 -         return;
 - 
 -     Path p;
 -     p.addEllipse (x, y, diameter, diameter);
 - 
 -     {
 -         ColourGradient cg (Colours::white.overlaidWith (colour.withMultipliedAlpha (0.3f)), 0, y,
 -                            Colours::white.overlaidWith (colour.withMultipliedAlpha (0.3f)), 0, y + diameter, false);
 - 
 -         cg.addColour (0.4, Colours::white.overlaidWith (colour));
 - 
 -         g.setGradientFill (cg);
 -         g.fillPath (p);
 -     }
 - 
 -     g.setGradientFill (ColourGradient (Colours::white, 0, y + diameter * 0.06f,
 -                                        Colours::transparentWhite, 0, y + diameter * 0.3f, false));
 -     g.fillEllipse (x + diameter * 0.2f, y + diameter * 0.05f, diameter * 0.6f, diameter * 0.4f);
 - 
 -     ColourGradient cg (Colours::transparentBlack,
 -                        x + diameter * 0.5f, y + diameter * 0.5f,
 -                        Colours::black.withAlpha (0.5f * outlineThickness * colour.getFloatAlpha()),
 -                        x, y + diameter * 0.5f, true);
 - 
 -     cg.addColour (0.7, Colours::transparentBlack);
 -     cg.addColour (0.8, Colours::black.withAlpha (0.1f * outlineThickness));
 - 
 -     g.setGradientFill (cg);
 -     g.fillPath (p);
 - 
 -     g.setColour (Colours::black.withAlpha (0.5f * colour.getFloatAlpha()));
 -     g.drawEllipse (x, y, diameter, diameter, outlineThickness);
 - }
 - 
 - //==============================================================================
 - void LookAndFeel_V2::drawGlassPointer (Graphics& g,
 -                                        const float x, const float y, const float diameter,
 -                                        const Colour& colour, const float outlineThickness,
 -                                        const int direction) noexcept
 - {
 -     if (diameter <= outlineThickness)
 -         return;
 - 
 -     Path p;
 -     p.startNewSubPath (x + diameter * 0.5f, y);
 -     p.lineTo (x + diameter, y + diameter * 0.6f);
 -     p.lineTo (x + diameter, y + diameter);
 -     p.lineTo (x, y + diameter);
 -     p.lineTo (x, y + diameter * 0.6f);
 -     p.closeSubPath();
 - 
 -     p.applyTransform (AffineTransform::rotation ((float) direction * MathConstants<float>::halfPi,
 -                                                  x + diameter * 0.5f,
 -                                                  y + diameter * 0.5f));
 - 
 -     {
 -         ColourGradient cg (Colours::white.overlaidWith (colour.withMultipliedAlpha (0.3f)), 0, y,
 -                            Colours::white.overlaidWith (colour.withMultipliedAlpha (0.3f)), 0, y + diameter, false);
 - 
 -         cg.addColour (0.4, Colours::white.overlaidWith (colour));
 - 
 -         g.setGradientFill (cg);
 -         g.fillPath (p);
 -     }
 - 
 -     ColourGradient cg (Colours::transparentBlack,
 -                        x + diameter * 0.5f, y + diameter * 0.5f,
 -                        Colours::black.withAlpha (0.5f * outlineThickness * colour.getFloatAlpha()),
 -                        x - diameter * 0.2f, y + diameter * 0.5f, true);
 - 
 -     cg.addColour (0.5, Colours::transparentBlack);
 -     cg.addColour (0.7, Colours::black.withAlpha (0.07f * outlineThickness));
 - 
 -     g.setGradientFill (cg);
 -     g.fillPath (p);
 - 
 -     g.setColour (Colours::black.withAlpha (0.5f * colour.getFloatAlpha()));
 -     g.strokePath (p, PathStrokeType (outlineThickness));
 - }
 - 
 - //==============================================================================
 - void LookAndFeel_V2::drawGlassLozenge (Graphics& g,
 -                                        float x, float y, float width, float height,
 -                                        const Colour& colour, float outlineThickness, float cornerSize,
 -                                        bool flatOnLeft, bool flatOnRight, bool flatOnTop, bool flatOnBottom) noexcept
 - {
 -     if (width <= outlineThickness || height <= outlineThickness)
 -         return;
 - 
 -     auto intX = (int) x;
 -     auto intY = (int) y;
 -     auto intW = (int) width;
 -     auto intH = (int) height;
 - 
 -     auto cs = cornerSize < 0 ? jmin (width * 0.5f, height * 0.5f) : cornerSize;
 -     auto edgeBlurRadius = height * 0.75f + (height - cs * 2.0f);
 -     auto intEdge = (int) edgeBlurRadius;
 - 
 -     Path outline;
 -     outline.addRoundedRectangle (x, y, width, height, cs, cs,
 -                                  ! (flatOnLeft || flatOnTop),
 -                                  ! (flatOnRight || flatOnTop),
 -                                  ! (flatOnLeft || flatOnBottom),
 -                                  ! (flatOnRight || flatOnBottom));
 - 
 -     {
 -         ColourGradient cg (colour.darker (0.2f), 0, y,
 -                            colour.darker (0.2f), 0, y + height, false);
 - 
 -         cg.addColour (0.03, colour.withMultipliedAlpha (0.3f));
 -         cg.addColour (0.4, colour);
 -         cg.addColour (0.97, colour.withMultipliedAlpha (0.3f));
 - 
 -         g.setGradientFill (cg);
 -         g.fillPath (outline);
 -     }
 - 
 -     ColourGradient cg (Colours::transparentBlack, x + edgeBlurRadius, y + height * 0.5f,
 -                        colour.darker (0.2f), x, y + height * 0.5f, true);
 - 
 -     cg.addColour (jlimit (0.0, 1.0, 1.0 - (cs * 0.5f) / edgeBlurRadius), Colours::transparentBlack);
 -     cg.addColour (jlimit (0.0, 1.0, 1.0 - (cs * 0.25f) / edgeBlurRadius), colour.darker (0.2f).withMultipliedAlpha (0.3f));
 - 
 -     if (! (flatOnLeft || flatOnTop || flatOnBottom))
 -     {
 -         Graphics::ScopedSaveState ss (g);
 - 
 -         g.setGradientFill (cg);
 -         g.reduceClipRegion (intX, intY, intEdge, intH);
 -         g.fillPath (outline);
 -     }
 - 
 -     if (! (flatOnRight || flatOnTop || flatOnBottom))
 -     {
 -         cg.point1.setX (x + width - edgeBlurRadius);
 -         cg.point2.setX (x + width);
 - 
 -         Graphics::ScopedSaveState ss (g);
 - 
 -         g.setGradientFill (cg);
 -         g.reduceClipRegion (intX + intW - intEdge, intY, 2 + intEdge, intH);
 -         g.fillPath (outline);
 -     }
 - 
 -     {
 -         auto leftIndent  = (flatOnTop || flatOnLeft)  ? 0.0f : cs * 0.4f;
 -         auto rightIndent = (flatOnTop || flatOnRight) ? 0.0f : cs * 0.4f;
 - 
 -         Path highlight;
 -         highlight.addRoundedRectangle (x + leftIndent,
 -                                        y + cs * 0.1f,
 -                                        width - (leftIndent + rightIndent),
 -                                        height * 0.4f,
 -                                        cs * 0.4f,
 -                                        cs * 0.4f,
 -                                        ! (flatOnLeft || flatOnTop),
 -                                        ! (flatOnRight || flatOnTop),
 -                                        ! (flatOnLeft || flatOnBottom),
 -                                        ! (flatOnRight || flatOnBottom));
 - 
 -         g.setGradientFill (ColourGradient (colour.brighter (10.0f), 0, y + height * 0.06f,
 -                                            Colours::transparentWhite, 0, y + height * 0.4f, false));
 -         g.fillPath (highlight);
 -     }
 - 
 -     g.setColour (colour.darker().withMultipliedAlpha (1.5f));
 -     g.strokePath (outline, PathStrokeType (outlineThickness));
 - }
 - 
 - } // namespace juce
 
 
  |