1 /*
2   ==============================================================================
3 
4    This file is part of the JUCE library.
5    Copyright (c) 2020 - Raw Material Software Limited
6 
7    JUCE is an open source library subject to commercial or open-source
8    licensing.
9 
10    By using JUCE, you agree to the terms of both the JUCE 6 End-User License
11    Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
12 
13    End User License Agreement: www.juce.com/juce-6-licence
14    Privacy Policy: www.juce.com/juce-privacy-policy
15 
16    Or: You may also use this code under the terms of the GPL v3 (see
17    www.gnu.org/licenses).
18 
19    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21    DISCLAIMED.
22 
23   ==============================================================================
24 */
25 
26 namespace juce
27 {
28 
getUIColour(UIColour index) const29 Colour LookAndFeel_V4::ColourScheme::getUIColour (UIColour index) const noexcept
30 {
31     if (isPositiveAndBelow (index, numColours))
32         return palette[index];
33 
34     jassertfalse;
35     return {};
36 }
37 
setUIColour(UIColour index,Colour newColour)38 void LookAndFeel_V4::ColourScheme::setUIColour (UIColour index, Colour newColour) noexcept
39 {
40     if (isPositiveAndBelow (index, numColours))
41         palette[index] = newColour;
42     else
43         jassertfalse;
44 }
45 
operator ==(const ColourScheme & other) const46 bool LookAndFeel_V4::ColourScheme::operator== (const ColourScheme& other) const noexcept
47 {
48     for (auto i = 0; i < numColours; ++i)
49         if (palette[i] != other.palette[i])
50             return false;
51 
52     return true;
53 }
54 
operator !=(const ColourScheme & other) const55 bool LookAndFeel_V4::ColourScheme::operator!= (const ColourScheme& other) const noexcept
56 {
57     return ! operator== (other);
58 }
59 
60 //==============================================================================
LookAndFeel_V4()61 LookAndFeel_V4::LookAndFeel_V4()  : currentColourScheme (getDarkColourScheme())
62 {
63     initialiseColours();
64 }
65 
LookAndFeel_V4(ColourScheme scheme)66 LookAndFeel_V4::LookAndFeel_V4 (ColourScheme scheme)  : currentColourScheme (scheme)
67 {
68     initialiseColours();
69 }
70 
~LookAndFeel_V4()71 LookAndFeel_V4::~LookAndFeel_V4()  {}
72 
73 //==============================================================================
setColourScheme(ColourScheme newColourScheme)74 void LookAndFeel_V4::setColourScheme (ColourScheme newColourScheme)
75 {
76     currentColourScheme = newColourScheme;
77     initialiseColours();
78 }
79 
getDarkColourScheme()80 LookAndFeel_V4::ColourScheme LookAndFeel_V4::getDarkColourScheme()
81 {
82     return { 0xff323e44, 0xff263238, 0xff323e44,
83              0xff8e989b, 0xffffffff, 0xff42a2c8,
84              0xffffffff, 0xff181f22, 0xffffffff };
85 }
86 
getMidnightColourScheme()87 LookAndFeel_V4::ColourScheme LookAndFeel_V4::getMidnightColourScheme()
88 {
89     return { 0xff2f2f3a, 0xff191926, 0xffd0d0d0,
90              0xff66667c, 0xc8ffffff, 0xffd8d8d8,
91              0xffffffff, 0xff606073, 0xff000000 };
92 }
93 
getGreyColourScheme()94 LookAndFeel_V4::ColourScheme LookAndFeel_V4::getGreyColourScheme()
95 {
96     return { 0xff505050, 0xff424242, 0xff606060,
97              0xffa6a6a6, 0xffffffff, 0xff21ba90,
98              0xff000000, 0xffffffff, 0xffffffff };
99 }
100 
getLightColourScheme()101 LookAndFeel_V4::ColourScheme LookAndFeel_V4::getLightColourScheme()
102 {
103     return { 0xffefefef, 0xffffffff, 0xffffffff,
104              0xffdddddd, 0xff000000, 0xffa9a9a9,
105              0xffffffff, 0xff42a2c8, 0xff000000 };
106 }
107 
108 //==============================================================================
109 class LookAndFeel_V4_DocumentWindowButton   : public Button
110 {
111 public:
LookAndFeel_V4_DocumentWindowButton(const String & name,Colour c,const Path & normal,const Path & toggled)112     LookAndFeel_V4_DocumentWindowButton (const String& name, Colour c, const Path& normal, const Path& toggled)
113         : Button (name), colour (c), normalShape (normal), toggledShape (toggled)
114     {
115     }
116 
paintButton(Graphics & g,bool shouldDrawButtonAsHighlighted,bool shouldDrawButtonAsDown)117     void paintButton (Graphics& g, bool shouldDrawButtonAsHighlighted, bool shouldDrawButtonAsDown) override
118     {
119         auto background = Colours::grey;
120 
121         if (auto* rw = findParentComponentOfClass<ResizableWindow>())
122             if (auto lf = dynamic_cast<LookAndFeel_V4*> (&rw->getLookAndFeel()))
123                 background = lf->getCurrentColourScheme().getUIColour (LookAndFeel_V4::ColourScheme::widgetBackground);
124 
125         g.fillAll (background);
126 
127         g.setColour ((! isEnabled() || shouldDrawButtonAsDown) ? colour.withAlpha (0.6f)
128                                                      : colour);
129 
130         if (shouldDrawButtonAsHighlighted)
131         {
132             g.fillAll();
133             g.setColour (background);
134         }
135 
136         auto& p = getToggleState() ? toggledShape : normalShape;
137 
138         auto reducedRect = Justification (Justification::centred)
139                               .appliedToRectangle (Rectangle<int> (getHeight(), getHeight()), getLocalBounds())
140                               .toFloat()
141                               .reduced ((float) getHeight() * 0.3f);
142 
143         g.fillPath (p, p.getTransformToScaleToFit (reducedRect, true));
144     }
145 
146 private:
147     Colour colour;
148     Path normalShape, toggledShape;
149 
150     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LookAndFeel_V4_DocumentWindowButton)
151 };
152 
createDocumentWindowButton(int buttonType)153 Button* LookAndFeel_V4::createDocumentWindowButton (int buttonType)
154 {
155     Path shape;
156     auto crossThickness = 0.15f;
157 
158     if (buttonType == DocumentWindow::closeButton)
159     {
160         shape.addLineSegment ({ 0.0f, 0.0f, 1.0f, 1.0f }, crossThickness);
161         shape.addLineSegment ({ 1.0f, 0.0f, 0.0f, 1.0f }, crossThickness);
162 
163         return new LookAndFeel_V4_DocumentWindowButton ("close", Colour (0xff9A131D), shape, shape);
164     }
165 
166     if (buttonType == DocumentWindow::minimiseButton)
167     {
168         shape.addLineSegment ({ 0.0f, 0.5f, 1.0f, 0.5f }, crossThickness);
169 
170         return new LookAndFeel_V4_DocumentWindowButton ("minimise", Colour (0xffaa8811), shape, shape);
171     }
172 
173     if (buttonType == DocumentWindow::maximiseButton)
174     {
175         shape.addLineSegment ({ 0.5f, 0.0f, 0.5f, 1.0f }, crossThickness);
176         shape.addLineSegment ({ 0.0f, 0.5f, 1.0f, 0.5f }, crossThickness);
177 
178         Path fullscreenShape;
179         fullscreenShape.startNewSubPath (45.0f, 100.0f);
180         fullscreenShape.lineTo (0.0f, 100.0f);
181         fullscreenShape.lineTo (0.0f, 0.0f);
182         fullscreenShape.lineTo (100.0f, 0.0f);
183         fullscreenShape.lineTo (100.0f, 45.0f);
184         fullscreenShape.addRectangle (45.0f, 45.0f, 100.0f, 100.0f);
185         PathStrokeType (30.0f).createStrokedPath (fullscreenShape, fullscreenShape);
186 
187         return new LookAndFeel_V4_DocumentWindowButton ("maximise", Colour (0xff0A830A), shape, fullscreenShape);
188     }
189 
190     jassertfalse;
191     return nullptr;
192 }
193 
positionDocumentWindowButtons(DocumentWindow &,int titleBarX,int titleBarY,int titleBarW,int titleBarH,Button * minimiseButton,Button * maximiseButton,Button * closeButton,bool positionTitleBarButtonsOnLeft)194 void LookAndFeel_V4::positionDocumentWindowButtons (DocumentWindow&,
195                                                     int titleBarX, int titleBarY,
196                                                     int titleBarW, int titleBarH,
197                                                     Button* minimiseButton,
198                                                     Button* maximiseButton,
199                                                     Button* closeButton,
200                                                     bool positionTitleBarButtonsOnLeft)
201 {
202     titleBarH = jmin (titleBarH, titleBarH - titleBarY);
203 
204     auto buttonW = static_cast<int> (titleBarH * 1.2);
205 
206     auto x = positionTitleBarButtonsOnLeft ? titleBarX
207                                            : titleBarX + titleBarW - buttonW;
208 
209     if (closeButton != nullptr)
210     {
211         closeButton->setBounds (x, titleBarY, buttonW, titleBarH);
212         x += positionTitleBarButtonsOnLeft ? buttonW : -buttonW;
213     }
214 
215     if (positionTitleBarButtonsOnLeft)
216         std::swap (minimiseButton, maximiseButton);
217 
218     if (maximiseButton != nullptr)
219     {
220         maximiseButton->setBounds (x, titleBarY, buttonW, titleBarH);
221         x += positionTitleBarButtonsOnLeft ? buttonW : -buttonW;
222     }
223 
224     if (minimiseButton != nullptr)
225         minimiseButton->setBounds (x, titleBarY, buttonW, titleBarH);
226 }
227 
drawDocumentWindowTitleBar(DocumentWindow & window,Graphics & g,int w,int h,int titleSpaceX,int titleSpaceW,const Image * icon,bool drawTitleTextOnLeft)228 void LookAndFeel_V4::drawDocumentWindowTitleBar (DocumentWindow& window, Graphics& g,
229                                                  int w, int h, int titleSpaceX, int titleSpaceW,
230                                                  const Image* icon, bool drawTitleTextOnLeft)
231 {
232     if (w * h == 0)
233         return;
234 
235     auto isActive = window.isActiveWindow();
236 
237     g.setColour (getCurrentColourScheme().getUIColour (ColourScheme::widgetBackground));
238     g.fillAll();
239 
240     Font font ((float) h * 0.65f, Font::plain);
241     g.setFont (font);
242 
243     auto textW = font.getStringWidth (window.getName());
244     auto iconW = 0;
245     auto iconH = 0;
246 
247     if (icon != nullptr)
248     {
249         iconH = static_cast<int> (font.getHeight());
250         iconW = icon->getWidth() * iconH / icon->getHeight() + 4;
251     }
252 
253     textW = jmin (titleSpaceW, textW + iconW);
254     auto textX = drawTitleTextOnLeft ? titleSpaceX
255                                      : jmax (titleSpaceX, (w - textW) / 2);
256 
257     if (textX + textW > titleSpaceX + titleSpaceW)
258         textX = titleSpaceX + titleSpaceW - textW;
259 
260     if (icon != nullptr)
261     {
262         g.setOpacity (isActive ? 1.0f : 0.6f);
263         g.drawImageWithin (*icon, textX, (h - iconH) / 2, iconW, iconH,
264                            RectanglePlacement::centred, false);
265         textX += iconW;
266         textW -= iconW;
267     }
268 
269     if (window.isColourSpecified (DocumentWindow::textColourId) || isColourSpecified (DocumentWindow::textColourId))
270         g.setColour (window.findColour (DocumentWindow::textColourId));
271     else
272         g.setColour (getCurrentColourScheme().getUIColour (ColourScheme::defaultText));
273 
274     g.drawText (window.getName(), textX, 0, textW, h, Justification::centredLeft, true);
275 }
276 
277 //==============================================================================
getTextButtonFont(TextButton &,int buttonHeight)278 Font LookAndFeel_V4::getTextButtonFont (TextButton&, int buttonHeight)
279 {
280     return { jmin (16.0f, (float) buttonHeight * 0.6f) };
281 }
282 
drawButtonBackground(Graphics & g,Button & button,const Colour & backgroundColour,bool shouldDrawButtonAsHighlighted,bool shouldDrawButtonAsDown)283 void LookAndFeel_V4::drawButtonBackground (Graphics& g,
284                                            Button& button,
285                                            const Colour& backgroundColour,
286                                            bool shouldDrawButtonAsHighlighted,
287                                            bool shouldDrawButtonAsDown)
288 {
289     auto cornerSize = 6.0f;
290     auto bounds = button.getLocalBounds().toFloat().reduced (0.5f, 0.5f);
291 
292     auto baseColour = backgroundColour.withMultipliedSaturation (button.hasKeyboardFocus (true) ? 1.3f : 0.9f)
293                                       .withMultipliedAlpha (button.isEnabled() ? 1.0f : 0.5f);
294 
295     if (shouldDrawButtonAsDown || shouldDrawButtonAsHighlighted)
296         baseColour = baseColour.contrasting (shouldDrawButtonAsDown ? 0.2f : 0.05f);
297 
298     g.setColour (baseColour);
299 
300     auto flatOnLeft   = button.isConnectedOnLeft();
301     auto flatOnRight  = button.isConnectedOnRight();
302     auto flatOnTop    = button.isConnectedOnTop();
303     auto flatOnBottom = button.isConnectedOnBottom();
304 
305     if (flatOnLeft || flatOnRight || flatOnTop || flatOnBottom)
306     {
307         Path path;
308         path.addRoundedRectangle (bounds.getX(), bounds.getY(),
309                                   bounds.getWidth(), bounds.getHeight(),
310                                   cornerSize, cornerSize,
311                                   ! (flatOnLeft  || flatOnTop),
312                                   ! (flatOnRight || flatOnTop),
313                                   ! (flatOnLeft  || flatOnBottom),
314                                   ! (flatOnRight || flatOnBottom));
315 
316         g.fillPath (path);
317 
318         g.setColour (button.findColour (ComboBox::outlineColourId));
319         g.strokePath (path, PathStrokeType (1.0f));
320     }
321     else
322     {
323         g.fillRoundedRectangle (bounds, cornerSize);
324 
325         g.setColour (button.findColour (ComboBox::outlineColourId));
326         g.drawRoundedRectangle (bounds, cornerSize, 1.0f);
327     }
328 }
329 
drawToggleButton(Graphics & g,ToggleButton & button,bool shouldDrawButtonAsHighlighted,bool shouldDrawButtonAsDown)330 void LookAndFeel_V4::drawToggleButton (Graphics& g, ToggleButton& button,
331                                        bool shouldDrawButtonAsHighlighted, bool shouldDrawButtonAsDown)
332 {
333     auto fontSize = jmin (15.0f, (float) button.getHeight() * 0.75f);
334     auto tickWidth = fontSize * 1.1f;
335 
336     drawTickBox (g, button, 4.0f, ((float) button.getHeight() - tickWidth) * 0.5f,
337                  tickWidth, tickWidth,
338                  button.getToggleState(),
339                  button.isEnabled(),
340                  shouldDrawButtonAsHighlighted,
341                  shouldDrawButtonAsDown);
342 
343     g.setColour (button.findColour (ToggleButton::textColourId));
344     g.setFont (fontSize);
345 
346     if (! button.isEnabled())
347         g.setOpacity (0.5f);
348 
349     g.drawFittedText (button.getButtonText(),
350                       button.getLocalBounds().withTrimmedLeft (roundToInt (tickWidth) + 10)
351                                              .withTrimmedRight (2),
352                       Justification::centredLeft, 10);
353 }
354 
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)355 void LookAndFeel_V4::drawTickBox (Graphics& g, Component& component,
356                                   float x, float y, float w, float h,
357                                   const bool ticked,
358                                   const bool isEnabled,
359                                   const bool shouldDrawButtonAsHighlighted,
360                                   const bool shouldDrawButtonAsDown)
361 {
362     ignoreUnused (isEnabled, shouldDrawButtonAsHighlighted, shouldDrawButtonAsDown);
363 
364     Rectangle<float> tickBounds (x, y, w, h);
365 
366     g.setColour (component.findColour (ToggleButton::tickDisabledColourId));
367     g.drawRoundedRectangle (tickBounds, 4.0f, 1.0f);
368 
369     if (ticked)
370     {
371         g.setColour (component.findColour (ToggleButton::tickColourId));
372         auto tick = getTickShape (0.75f);
373         g.fillPath (tick, tick.getTransformToScaleToFit (tickBounds.reduced (4, 5).toFloat(), false));
374     }
375 }
376 
changeToggleButtonWidthToFitText(ToggleButton & button)377 void LookAndFeel_V4::changeToggleButtonWidthToFitText (ToggleButton& button)
378 {
379     auto fontSize = jmin (15.0f, (float) button.getHeight() * 0.75f);
380     auto tickWidth = fontSize * 1.1f;
381 
382     Font font (fontSize);
383 
384     button.setSize (font.getStringWidth (button.getButtonText()) + roundToInt (tickWidth) + 14, button.getHeight());
385 }
386 
387 //==============================================================================
createAlertWindow(const String & title,const String & message,const String & button1,const String & button2,const String & button3,AlertWindow::AlertIconType iconType,int numButtons,Component * associatedComponent)388 AlertWindow* LookAndFeel_V4::createAlertWindow (const String& title, const String& message,
389                                                 const String& button1, const String& button2, const String& button3,
390                                                 AlertWindow::AlertIconType iconType,
391                                                 int numButtons, Component* associatedComponent)
392 {
393     auto boundsOffset = 50;
394 
395     auto* aw = LookAndFeel_V2::createAlertWindow (title, message, button1, button2, button3,
396                                                   iconType, numButtons, associatedComponent);
397 
398     auto bounds = aw->getBounds();
399     bounds = bounds.withSizeKeepingCentre (bounds.getWidth() + boundsOffset, bounds.getHeight() + boundsOffset);
400     aw->setBounds (bounds);
401 
402     for (auto* child : aw->getChildren())
403         if (auto* button = dynamic_cast<TextButton*> (child))
404             button->setBounds (button->getBounds() + Point<int> (25, 40));
405 
406     return aw;
407 }
408 
drawAlertBox(Graphics & g,AlertWindow & alert,const Rectangle<int> & textArea,TextLayout & textLayout)409 void LookAndFeel_V4::drawAlertBox (Graphics& g, AlertWindow& alert,
410                                    const Rectangle<int>& textArea, TextLayout& textLayout)
411 {
412     auto cornerSize = 4.0f;
413 
414     g.setColour (alert.findColour (AlertWindow::outlineColourId));
415     g.drawRoundedRectangle (alert.getLocalBounds().toFloat(), cornerSize, 2.0f);
416 
417     auto bounds = alert.getLocalBounds().reduced (1);
418     g.reduceClipRegion (bounds);
419 
420     g.setColour (alert.findColour (AlertWindow::backgroundColourId));
421     g.fillRoundedRectangle (bounds.toFloat(), cornerSize);
422 
423     auto iconSpaceUsed = 0;
424 
425     auto iconWidth = 80;
426     auto iconSize = jmin (iconWidth + 50, bounds.getHeight() + 20);
427 
428     if (alert.containsAnyExtraComponents() || alert.getNumButtons() > 2)
429         iconSize = jmin (iconSize, textArea.getHeight() + 50);
430 
431     Rectangle<int> iconRect (iconSize / -10, iconSize / -10,
432                              iconSize, iconSize);
433 
434     if (alert.getAlertType() != AlertWindow::NoIcon)
435     {
436         Path icon;
437         char character;
438         uint32 colour;
439 
440         if (alert.getAlertType() == AlertWindow::WarningIcon)
441         {
442             character = '!';
443 
444             icon.addTriangle ((float) iconRect.getX() + (float) iconRect.getWidth() * 0.5f, (float) iconRect.getY(),
445                               static_cast<float> (iconRect.getRight()), static_cast<float> (iconRect.getBottom()),
446                               static_cast<float> (iconRect.getX()), static_cast<float> (iconRect.getBottom()));
447 
448             icon = icon.createPathWithRoundedCorners (5.0f);
449             colour = 0x66ff2a00;
450         }
451         else
452         {
453             colour = Colour (0xff00b0b9).withAlpha (0.4f).getARGB();
454             character = alert.getAlertType() == AlertWindow::InfoIcon ? 'i' : '?';
455 
456             icon.addEllipse (iconRect.toFloat());
457         }
458 
459         GlyphArrangement ga;
460         ga.addFittedText ({ (float) iconRect.getHeight() * 0.9f, Font::bold },
461                           String::charToString ((juce_wchar) (uint8) character),
462                           static_cast<float> (iconRect.getX()), static_cast<float> (iconRect.getY()),
463                           static_cast<float> (iconRect.getWidth()), static_cast<float> (iconRect.getHeight()),
464                           Justification::centred, false);
465         ga.createPath (icon);
466 
467         icon.setUsingNonZeroWinding (false);
468         g.setColour (Colour (colour));
469         g.fillPath (icon);
470 
471         iconSpaceUsed = iconWidth;
472     }
473 
474     g.setColour (alert.findColour (AlertWindow::textColourId));
475 
476     Rectangle<int> alertBounds (bounds.getX() + iconSpaceUsed, 30,
477                                 bounds.getWidth(), bounds.getHeight() - getAlertWindowButtonHeight() - 20);
478 
479     textLayout.draw (g, alertBounds.toFloat());
480 }
481 
getAlertWindowButtonHeight()482 int LookAndFeel_V4::getAlertWindowButtonHeight()    { return 40; }
getAlertWindowTitleFont()483 Font LookAndFeel_V4::getAlertWindowTitleFont()      { return { 18.0f, Font::bold }; }
getAlertWindowMessageFont()484 Font LookAndFeel_V4::getAlertWindowMessageFont()    { return { 16.0f }; }
getAlertWindowFont()485 Font LookAndFeel_V4::getAlertWindowFont()           { return { 14.0f }; }
486 
487 //==============================================================================
drawProgressBar(Graphics & g,ProgressBar & progressBar,int width,int height,double progress,const String & textToShow)488 void LookAndFeel_V4::drawProgressBar (Graphics& g, ProgressBar& progressBar,
489                                       int width, int height, double progress, const String& textToShow)
490 {
491     if (width == height)
492         drawCircularProgressBar (g, progressBar, textToShow);
493     else
494         drawLinearProgressBar (g, progressBar, width, height, progress, textToShow);
495 }
496 
drawLinearProgressBar(Graphics & g,ProgressBar & progressBar,int width,int height,double progress,const String & textToShow)497 void LookAndFeel_V4::drawLinearProgressBar (Graphics& g, ProgressBar& progressBar,
498                                             int width, int height,
499                                             double progress, const String& textToShow)
500 {
501     auto background = progressBar.findColour (ProgressBar::backgroundColourId);
502     auto foreground = progressBar.findColour (ProgressBar::foregroundColourId);
503 
504     auto barBounds = progressBar.getLocalBounds().toFloat();
505 
506     g.setColour (background);
507     g.fillRoundedRectangle (barBounds, (float) progressBar.getHeight() * 0.5f);
508 
509     if (progress >= 0.0f && progress <= 1.0f)
510     {
511         Path p;
512         p.addRoundedRectangle (barBounds, (float) progressBar.getHeight() * 0.5f);
513         g.reduceClipRegion (p);
514 
515         barBounds.setWidth (barBounds.getWidth() * (float) progress);
516         g.setColour (foreground);
517         g.fillRoundedRectangle (barBounds, (float) progressBar.getHeight() * 0.5f);
518     }
519     else
520     {
521         // spinning bar..
522         g.setColour (background);
523 
524         auto stripeWidth = height * 2;
525         auto position = static_cast<int> (Time::getMillisecondCounter() / 15) % stripeWidth;
526 
527         Path p;
528 
529         for (auto x = static_cast<float> (-position); x < (float) (width + stripeWidth); x += (float) stripeWidth)
530             p.addQuadrilateral (x, 0.0f,
531                                 x + (float) stripeWidth * 0.5f, 0.0f,
532                                 x, static_cast<float> (height),
533                                 x - (float) stripeWidth * 0.5f, static_cast<float> (height));
534 
535         Image im (Image::ARGB, width, height, true);
536 
537         {
538             Graphics g2 (im);
539             g2.setColour (foreground);
540             g2.fillRoundedRectangle (barBounds, (float) progressBar.getHeight() * 0.5f);
541         }
542 
543         g.setTiledImageFill (im, 0, 0, 0.85f);
544         g.fillPath (p);
545     }
546 
547     if (textToShow.isNotEmpty())
548     {
549         g.setColour (Colour::contrasting (background, foreground));
550         g.setFont ((float) height * 0.6f);
551 
552         g.drawText (textToShow, 0, 0, width, height, Justification::centred, false);
553     }
554 }
555 
drawCircularProgressBar(Graphics & g,ProgressBar & progressBar,const String & progressText)556 void LookAndFeel_V4::drawCircularProgressBar (Graphics& g, ProgressBar& progressBar, const String& progressText)
557 {
558     auto background = progressBar.findColour (ProgressBar::backgroundColourId);
559     auto foreground = progressBar.findColour (ProgressBar::foregroundColourId);
560 
561     auto barBounds = progressBar.getLocalBounds().reduced (2, 2).toFloat();
562 
563     auto rotationInDegrees  = static_cast<float> ((Time::getMillisecondCounter() / 10) % 360);
564     auto normalisedRotation = rotationInDegrees / 360.0f;
565 
566     auto rotationOffset = 22.5f;
567     auto maxRotation    = 315.0f;
568 
569     auto startInDegrees = rotationInDegrees;
570     auto endInDegrees   = startInDegrees + rotationOffset;
571 
572     if (normalisedRotation >= 0.25f && normalisedRotation < 0.5f)
573     {
574         auto rescaledRotation = (normalisedRotation * 4.0f) - 1.0f;
575         endInDegrees = startInDegrees + rotationOffset + (maxRotation * rescaledRotation);
576     }
577     else if (normalisedRotation >= 0.5f && normalisedRotation <= 1.0f)
578     {
579         endInDegrees = startInDegrees + rotationOffset + maxRotation;
580         auto rescaledRotation = 1.0f - ((normalisedRotation * 2.0f) - 1.0f);
581         startInDegrees = endInDegrees - rotationOffset - (maxRotation * rescaledRotation);
582     }
583 
584     g.setColour (background);
585     Path arcPath2;
586     arcPath2.addCentredArc (barBounds.getCentreX(),
587                             barBounds.getCentreY(),
588                             barBounds.getWidth() * 0.5f,
589                             barBounds.getHeight() * 0.5f, 0.0f,
590                             0.0f,
591                             MathConstants<float>::twoPi,
592                             true);
593     g.strokePath (arcPath2, PathStrokeType (4.0f));
594 
595     g.setColour (foreground);
596     Path arcPath;
597     arcPath.addCentredArc (barBounds.getCentreX(),
598                            barBounds.getCentreY(),
599                            barBounds.getWidth() * 0.5f,
600                            barBounds.getHeight() * 0.5f,
601                            0.0f,
602                            degreesToRadians (startInDegrees),
603                            degreesToRadians (endInDegrees),
604                            true);
605 
606     arcPath.applyTransform (AffineTransform::rotation (normalisedRotation * MathConstants<float>::pi * 2.25f, barBounds.getCentreX(), barBounds.getCentreY()));
607     g.strokePath (arcPath, PathStrokeType (4.0f));
608 
609     if (progressText.isNotEmpty())
610     {
611         g.setColour (progressBar.findColour (TextButton::textColourOffId));
612         g.setFont ({ 12.0f, Font::italic });
613         g.drawText (progressText, barBounds, Justification::centred, false);
614     }
615 }
616 
617 //==============================================================================
getDefaultScrollbarWidth()618 int LookAndFeel_V4::getDefaultScrollbarWidth()
619 {
620     return 8;
621 }
622 
drawScrollbar(Graphics & g,ScrollBar & scrollbar,int x,int y,int width,int height,bool isScrollbarVertical,int thumbStartPosition,int thumbSize,bool isMouseOver,bool isMouseDown)623 void LookAndFeel_V4::drawScrollbar (Graphics& g, ScrollBar& scrollbar, int x, int y, int width, int height,
624                                     bool isScrollbarVertical, int thumbStartPosition, int thumbSize, bool isMouseOver, bool isMouseDown)
625 {
626     ignoreUnused (isMouseDown);
627 
628     Rectangle<int> thumbBounds;
629 
630     if (isScrollbarVertical)
631         thumbBounds = { x, thumbStartPosition, width, thumbSize };
632     else
633         thumbBounds = { thumbStartPosition, y, thumbSize, height };
634 
635     auto c = scrollbar.findColour (ScrollBar::ColourIds::thumbColourId);
636     g.setColour (isMouseOver ? c.brighter (0.25f) : c);
637     g.fillRoundedRectangle (thumbBounds.reduced (1).toFloat(), 4.0f);
638 }
639 
640 //==============================================================================
getTickShape(float height)641 Path LookAndFeel_V4::getTickShape (float height)
642 {
643     static const unsigned char pathData[] = { 110,109,32,210,202,64,126,183,148,64,108,39,244,247,64,245,76,124,64,108,178,131,27,65,246,76,252,64,108,175,242,4,65,246,76,252,
644         64,108,236,5,68,65,0,0,160,180,108,240,150,90,65,21,136,52,63,108,48,59,16,65,0,0,32,65,108,32,210,202,64,126,183,148,64, 99,101,0,0 };
645 
646     Path path;
647     path.loadPathFromData (pathData, sizeof (pathData));
648     path.scaleToFit (0, 0, height * 2.0f, height, true);
649 
650     return path;
651 }
652 
getCrossShape(float height)653 Path LookAndFeel_V4::getCrossShape (float height)
654 {
655     static const unsigned char pathData[] = { 110,109,51,51,255,66,0,0,0,0,108,205,204,13,67,51,51,99,65,108,0,0,170,66,205,204,141,66,108,51,179,13,67,52,51,255,66,108,0,0,255,
656         66,205,204,13,67,108,205,204,141,66,0,0,170,66,108,52,51,99,65,51,179,13,67,108,0,0,0,0,51,51,255,66,108,205,204,98,66, 204,204,141,66,108,0,0,0,0,51,51,99,65,108,51,51,
657         99,65,0,0,0,0,108,205,204,141,66,205,204,98,66,108,51,51,255,66,0,0,0,0,99,101,0,0 };
658 
659     Path path;
660     path.loadPathFromData (pathData, sizeof (pathData));
661     path.scaleToFit (0, 0, height * 2.0f, height, true);
662 
663     return path;
664 }
665 
666 //==============================================================================
fillTextEditorBackground(Graphics & g,int width,int height,TextEditor & textEditor)667 void LookAndFeel_V4::fillTextEditorBackground (Graphics& g, int width, int height, TextEditor& textEditor)
668 {
669     if (dynamic_cast<AlertWindow*> (textEditor.getParentComponent()) != nullptr)
670     {
671         g.setColour (textEditor.findColour (TextEditor::backgroundColourId));
672         g.fillRect (0, 0, width, height);
673 
674         g.setColour (textEditor.findColour (TextEditor::outlineColourId));
675         g.drawHorizontalLine (height - 1, 0.0f, static_cast<float> (width));
676     }
677     else
678     {
679         LookAndFeel_V2::fillTextEditorBackground (g, width, height, textEditor);
680     }
681 }
682 
drawTextEditorOutline(Graphics & g,int width,int height,TextEditor & textEditor)683 void LookAndFeel_V4::drawTextEditorOutline (Graphics& g, int width, int height, TextEditor& textEditor)
684 {
685     if (dynamic_cast<AlertWindow*> (textEditor.getParentComponent()) == nullptr)
686     {
687         if (textEditor.isEnabled())
688         {
689             if (textEditor.hasKeyboardFocus (true) && ! textEditor.isReadOnly())
690             {
691                 g.setColour (textEditor.findColour (TextEditor::focusedOutlineColourId));
692                 g.drawRect (0, 0, width, height, 2);
693             }
694             else
695             {
696                 g.setColour (textEditor.findColour (TextEditor::outlineColourId));
697                 g.drawRect (0, 0, width, height);
698             }
699         }
700     }
701 }
702 
703 //==============================================================================
createFileBrowserGoUpButton()704 Button* LookAndFeel_V4::createFileBrowserGoUpButton()
705 {
706     auto* goUpButton = new DrawableButton ("up", DrawableButton::ImageOnButtonBackground);
707 
708     Path arrowPath;
709     arrowPath.addArrow ({ 50.0f, 100.0f, 50.0f, 0.0f }, 40.0f, 100.0f, 50.0f);
710 
711     DrawablePath arrowImage;
712     arrowImage.setFill (goUpButton->findColour (TextButton::textColourOffId));
713     arrowImage.setPath (arrowPath);
714 
715     goUpButton->setImages (&arrowImage);
716 
717     return goUpButton;
718 }
719 
layoutFileBrowserComponent(FileBrowserComponent & browserComp,DirectoryContentsDisplayComponent * fileListComponent,FilePreviewComponent * previewComp,ComboBox * currentPathBox,TextEditor * filenameBox,Button * goUpButton)720 void LookAndFeel_V4::layoutFileBrowserComponent (FileBrowserComponent& browserComp,
721                                                  DirectoryContentsDisplayComponent* fileListComponent,
722                                                  FilePreviewComponent* previewComp,
723                                                  ComboBox* currentPathBox,
724                                                  TextEditor* filenameBox,
725                                                  Button* goUpButton)
726 {
727     auto sectionHeight = 22;
728     auto buttonWidth = 50;
729 
730     auto b = browserComp.getLocalBounds().reduced (20, 5);
731 
732     auto topSlice    = b.removeFromTop (sectionHeight);
733     auto bottomSlice = b.removeFromBottom (sectionHeight);
734 
735     currentPathBox->setBounds (topSlice.removeFromLeft (topSlice.getWidth() - buttonWidth));
736 
737     topSlice.removeFromLeft (6);
738     goUpButton->setBounds (topSlice);
739 
740     bottomSlice.removeFromLeft (20);
741     filenameBox->setBounds (bottomSlice);
742 
743     if (previewComp != nullptr)
744         previewComp->setBounds (b.removeFromRight (b.getWidth() / 3));
745 
746     if (auto* listAsComp = dynamic_cast<Component*> (fileListComponent))
747         listAsComp->setBounds (b.reduced (0, 10));
748 }
749 
drawFileBrowserRow(Graphics & g,int width,int height,const File & file,const String & filename,Image * icon,const String & fileSizeDescription,const String & fileTimeDescription,bool isDirectory,bool isItemSelected,int itemIndex,DirectoryContentsDisplayComponent & dcc)750 void LookAndFeel_V4::drawFileBrowserRow (Graphics& g, int width, int height,
751                                          const File& file, const String& filename, Image* icon,
752                                          const String& fileSizeDescription,
753                                          const String& fileTimeDescription,
754                                          bool isDirectory, bool isItemSelected,
755                                          int itemIndex, DirectoryContentsDisplayComponent& dcc)
756 {
757     LookAndFeel_V2::drawFileBrowserRow (g, width, height, file, filename, icon,
758                                         fileSizeDescription, fileTimeDescription,
759                                         isDirectory, isItemSelected, itemIndex, dcc);
760 }
761 
762 //==============================================================================
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)763 void LookAndFeel_V4::drawPopupMenuItem (Graphics& g, const Rectangle<int>& area,
764                                         const bool isSeparator, const bool isActive,
765                                         const bool isHighlighted, const bool isTicked,
766                                         const bool hasSubMenu, const String& text,
767                                         const String& shortcutKeyText,
768                                         const Drawable* icon, const Colour* const textColourToUse)
769 {
770     if (isSeparator)
771     {
772         auto r  = area.reduced (5, 0);
773         r.removeFromTop (roundToInt (((float) r.getHeight() * 0.5f) - 0.5f));
774 
775         g.setColour (findColour (PopupMenu::textColourId).withAlpha (0.3f));
776         g.fillRect (r.removeFromTop (1));
777     }
778     else
779     {
780         auto textColour = (textColourToUse == nullptr ? findColour (PopupMenu::textColourId)
781                                                       : *textColourToUse);
782 
783         auto r  = area.reduced (1);
784 
785         if (isHighlighted && isActive)
786         {
787             g.setColour (findColour (PopupMenu::highlightedBackgroundColourId));
788             g.fillRect (r);
789 
790             g.setColour (findColour (PopupMenu::highlightedTextColourId));
791         }
792         else
793         {
794             g.setColour (textColour.withMultipliedAlpha (isActive ? 1.0f : 0.5f));
795         }
796 
797         r.reduce (jmin (5, area.getWidth() / 20), 0);
798 
799         auto font = getPopupMenuFont();
800 
801         auto maxFontHeight = (float) r.getHeight() / 1.3f;
802 
803         if (font.getHeight() > maxFontHeight)
804             font.setHeight (maxFontHeight);
805 
806         g.setFont (font);
807 
808         auto iconArea = r.removeFromLeft (roundToInt (maxFontHeight)).toFloat();
809 
810         if (icon != nullptr)
811         {
812             icon->drawWithin (g, iconArea, RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize, 1.0f);
813             r.removeFromLeft (roundToInt (maxFontHeight * 0.5f));
814         }
815         else if (isTicked)
816         {
817             auto tick = getTickShape (1.0f);
818             g.fillPath (tick, tick.getTransformToScaleToFit (iconArea.reduced (iconArea.getWidth() / 5, 0).toFloat(), true));
819         }
820 
821         if (hasSubMenu)
822         {
823             auto arrowH = 0.6f * getPopupMenuFont().getAscent();
824 
825             auto x = static_cast<float> (r.removeFromRight ((int) arrowH).getX());
826             auto halfH = static_cast<float> (r.getCentreY());
827 
828             Path path;
829             path.startNewSubPath (x, halfH - arrowH * 0.5f);
830             path.lineTo (x + arrowH * 0.6f, halfH);
831             path.lineTo (x, halfH + arrowH * 0.5f);
832 
833             g.strokePath (path, PathStrokeType (2.0f));
834         }
835 
836         r.removeFromRight (3);
837         g.drawFittedText (text, r, Justification::centredLeft, 1);
838 
839         if (shortcutKeyText.isNotEmpty())
840         {
841             auto f2 = font;
842             f2.setHeight (f2.getHeight() * 0.75f);
843             f2.setHorizontalScale (0.95f);
844             g.setFont (f2);
845 
846             g.drawText (shortcutKeyText, r, Justification::centredRight, true);
847         }
848     }
849 }
850 
getIdealPopupMenuItemSize(const String & text,const bool isSeparator,int standardMenuItemHeight,int & idealWidth,int & idealHeight)851 void LookAndFeel_V4::getIdealPopupMenuItemSize (const String& text, const bool isSeparator,
852                                                 int standardMenuItemHeight, int& idealWidth, int& idealHeight)
853 {
854     if (isSeparator)
855     {
856         idealWidth = 50;
857         idealHeight = standardMenuItemHeight > 0 ? standardMenuItemHeight / 10 : 10;
858     }
859     else
860     {
861         auto font = getPopupMenuFont();
862 
863         if (standardMenuItemHeight > 0 && font.getHeight() > (float) standardMenuItemHeight / 1.3f)
864             font.setHeight ((float) standardMenuItemHeight / 1.3f);
865 
866         idealHeight = standardMenuItemHeight > 0 ? standardMenuItemHeight : roundToInt (font.getHeight() * 1.3f);
867         idealWidth = font.getStringWidth (text) + idealHeight * 2;
868     }
869 }
870 
drawMenuBarBackground(Graphics & g,int width,int height,bool,MenuBarComponent & menuBar)871 void LookAndFeel_V4::drawMenuBarBackground (Graphics& g, int width, int height,
872                                             bool, MenuBarComponent& menuBar)
873 {
874     auto colour = menuBar.findColour (TextButton::buttonColourId).withAlpha (0.4f);
875 
876     Rectangle<int> r (width, height);
877 
878     g.setColour (colour.contrasting (0.15f));
879     g.fillRect  (r.removeFromTop (1));
880     g.fillRect  (r.removeFromBottom (1));
881 
882     g.setGradientFill (ColourGradient::vertical (colour, 0, colour.darker (0.2f), (float) height));
883     g.fillRect (r);
884 }
885 
drawMenuBarItem(Graphics & g,int width,int height,int itemIndex,const String & itemText,bool isMouseOverItem,bool isMenuOpen,bool,MenuBarComponent & menuBar)886 void LookAndFeel_V4::drawMenuBarItem (Graphics& g, int width, int height,
887                                       int itemIndex, const String& itemText,
888                                       bool isMouseOverItem, bool isMenuOpen,
889                                       bool /*isMouseOverBar*/, MenuBarComponent& menuBar)
890 {
891     if (! menuBar.isEnabled())
892     {
893         g.setColour (menuBar.findColour (TextButton::textColourOffId)
894                             .withMultipliedAlpha (0.5f));
895     }
896     else if (isMenuOpen || isMouseOverItem)
897     {
898         g.fillAll   (menuBar.findColour (TextButton::buttonOnColourId));
899         g.setColour (menuBar.findColour (TextButton::textColourOnId));
900     }
901     else
902     {
903         g.setColour (menuBar.findColour (TextButton::textColourOffId));
904     }
905 
906     g.setFont (getMenuBarFont (menuBar, itemIndex, itemText));
907     g.drawFittedText (itemText, 0, 0, width, height, Justification::centred, 1);
908 }
909 
910 //==============================================================================
drawComboBox(Graphics & g,int width,int height,bool,int,int,int,int,ComboBox & box)911 void LookAndFeel_V4::drawComboBox (Graphics& g, int width, int height, bool,
912                                    int, int, int, int, ComboBox& box)
913 {
914     auto cornerSize = box.findParentComponentOfClass<ChoicePropertyComponent>() != nullptr ? 0.0f : 3.0f;
915     Rectangle<int> boxBounds (0, 0, width, height);
916 
917     g.setColour (box.findColour (ComboBox::backgroundColourId));
918     g.fillRoundedRectangle (boxBounds.toFloat(), cornerSize);
919 
920     g.setColour (box.findColour (ComboBox::outlineColourId));
921     g.drawRoundedRectangle (boxBounds.toFloat().reduced (0.5f, 0.5f), cornerSize, 1.0f);
922 
923     Rectangle<int> arrowZone (width - 30, 0, 20, height);
924     Path path;
925     path.startNewSubPath ((float) arrowZone.getX() + 3.0f, (float) arrowZone.getCentreY() - 2.0f);
926     path.lineTo ((float) arrowZone.getCentreX(), (float) arrowZone.getCentreY() + 3.0f);
927     path.lineTo ((float) arrowZone.getRight() - 3.0f, (float) arrowZone.getCentreY() - 2.0f);
928 
929     g.setColour (box.findColour (ComboBox::arrowColourId).withAlpha ((box.isEnabled() ? 0.9f : 0.2f)));
930     g.strokePath (path, PathStrokeType (2.0f));
931 }
932 
getComboBoxFont(ComboBox & box)933 Font LookAndFeel_V4::getComboBoxFont (ComboBox& box)
934 {
935     return { jmin (16.0f, (float) box.getHeight() * 0.85f) };
936 }
937 
positionComboBoxText(ComboBox & box,Label & label)938 void LookAndFeel_V4::positionComboBoxText (ComboBox& box, Label& label)
939 {
940     label.setBounds (1, 1,
941                      box.getWidth() - 30,
942                      box.getHeight() - 2);
943 
944     label.setFont (getComboBoxFont (box));
945 }
946 
947 //==============================================================================
getSliderThumbRadius(Slider & slider)948 int LookAndFeel_V4::getSliderThumbRadius (Slider& slider)
949 {
950     return jmin (12, slider.isHorizontal() ? static_cast<int> ((float) slider.getHeight() * 0.5f)
951                                            : static_cast<int> ((float) slider.getWidth()  * 0.5f));
952 }
953 
drawLinearSlider(Graphics & g,int x,int y,int width,int height,float sliderPos,float minSliderPos,float maxSliderPos,const Slider::SliderStyle style,Slider & slider)954 void LookAndFeel_V4::drawLinearSlider (Graphics& g, int x, int y, int width, int height,
955                                        float sliderPos,
956                                        float minSliderPos,
957                                        float maxSliderPos,
958                                        const Slider::SliderStyle style, Slider& slider)
959 {
960     if (slider.isBar())
961     {
962         g.setColour (slider.findColour (Slider::trackColourId));
963         g.fillRect (slider.isHorizontal() ? Rectangle<float> (static_cast<float> (x), (float) y + 0.5f, sliderPos - (float) x, (float) height - 1.0f)
964                                           : Rectangle<float> ((float) x + 0.5f, sliderPos, (float) width - 1.0f, (float) y + ((float) height - sliderPos)));
965     }
966     else
967     {
968         auto isTwoVal   = (style == Slider::SliderStyle::TwoValueVertical   || style == Slider::SliderStyle::TwoValueHorizontal);
969         auto isThreeVal = (style == Slider::SliderStyle::ThreeValueVertical || style == Slider::SliderStyle::ThreeValueHorizontal);
970 
971         auto trackWidth = jmin (6.0f, slider.isHorizontal() ? (float) height * 0.25f : (float) width * 0.25f);
972 
973         Point<float> startPoint (slider.isHorizontal() ? (float) x : (float) x + (float) width * 0.5f,
974                                  slider.isHorizontal() ? (float) y + (float) height * 0.5f : (float) (height + y));
975 
976         Point<float> endPoint (slider.isHorizontal() ? (float) (width + x) : startPoint.x,
977                                slider.isHorizontal() ? startPoint.y : (float) y);
978 
979         Path backgroundTrack;
980         backgroundTrack.startNewSubPath (startPoint);
981         backgroundTrack.lineTo (endPoint);
982         g.setColour (slider.findColour (Slider::backgroundColourId));
983         g.strokePath (backgroundTrack, { trackWidth, PathStrokeType::curved, PathStrokeType::rounded });
984 
985         Path valueTrack;
986         Point<float> minPoint, maxPoint, thumbPoint;
987 
988         if (isTwoVal || isThreeVal)
989         {
990             minPoint = { slider.isHorizontal() ? minSliderPos : (float) width * 0.5f,
991                          slider.isHorizontal() ? (float) height * 0.5f : minSliderPos };
992 
993             if (isThreeVal)
994                 thumbPoint = { slider.isHorizontal() ? sliderPos : (float) width * 0.5f,
995                                slider.isHorizontal() ? (float) height * 0.5f : sliderPos };
996 
997             maxPoint = { slider.isHorizontal() ? maxSliderPos : (float) width * 0.5f,
998                          slider.isHorizontal() ? (float) height * 0.5f : maxSliderPos };
999         }
1000         else
1001         {
1002             auto kx = slider.isHorizontal() ? sliderPos : ((float) x + (float) width * 0.5f);
1003             auto ky = slider.isHorizontal() ? ((float) y + (float) height * 0.5f) : sliderPos;
1004 
1005             minPoint = startPoint;
1006             maxPoint = { kx, ky };
1007         }
1008 
1009         auto thumbWidth = getSliderThumbRadius (slider);
1010 
1011         valueTrack.startNewSubPath (minPoint);
1012         valueTrack.lineTo (isThreeVal ? thumbPoint : maxPoint);
1013         g.setColour (slider.findColour (Slider::trackColourId));
1014         g.strokePath (valueTrack, { trackWidth, PathStrokeType::curved, PathStrokeType::rounded });
1015 
1016         if (! isTwoVal)
1017         {
1018             g.setColour (slider.findColour (Slider::thumbColourId));
1019             g.fillEllipse (Rectangle<float> (static_cast<float> (thumbWidth), static_cast<float> (thumbWidth)).withCentre (isThreeVal ? thumbPoint : maxPoint));
1020         }
1021 
1022         if (isTwoVal || isThreeVal)
1023         {
1024             auto sr = jmin (trackWidth, (slider.isHorizontal() ? (float) height : (float) width) * 0.4f);
1025             auto pointerColour = slider.findColour (Slider::thumbColourId);
1026 
1027             if (slider.isHorizontal())
1028             {
1029                 drawPointer (g, minSliderPos - sr,
1030                              jmax (0.0f, (float) y + (float) height * 0.5f - trackWidth * 2.0f),
1031                              trackWidth * 2.0f, pointerColour, 2);
1032 
1033                 drawPointer (g, maxSliderPos - trackWidth,
1034                              jmin ((float) (y + height) - trackWidth * 2.0f, (float) y + (float) height * 0.5f),
1035                              trackWidth * 2.0f, pointerColour, 4);
1036             }
1037             else
1038             {
1039                 drawPointer (g, jmax (0.0f, (float) x + (float) width * 0.5f - trackWidth * 2.0f),
1040                              minSliderPos - trackWidth,
1041                              trackWidth * 2.0f, pointerColour, 1);
1042 
1043                 drawPointer (g, jmin ((float) (x + width) - trackWidth * 2.0f, (float) x + (float) width * 0.5f), maxSliderPos - sr,
1044                              trackWidth * 2.0f, pointerColour, 3);
1045             }
1046         }
1047     }
1048 }
1049 
drawRotarySlider(Graphics & g,int x,int y,int width,int height,float sliderPos,const float rotaryStartAngle,const float rotaryEndAngle,Slider & slider)1050 void LookAndFeel_V4::drawRotarySlider (Graphics& g, int x, int y, int width, int height, float sliderPos,
1051                                        const float rotaryStartAngle, const float rotaryEndAngle, Slider& slider)
1052 {
1053     auto outline = slider.findColour (Slider::rotarySliderOutlineColourId);
1054     auto fill    = slider.findColour (Slider::rotarySliderFillColourId);
1055 
1056     auto bounds = Rectangle<int> (x, y, width, height).toFloat().reduced (10);
1057 
1058     auto radius = jmin (bounds.getWidth(), bounds.getHeight()) / 2.0f;
1059     auto toAngle = rotaryStartAngle + sliderPos * (rotaryEndAngle - rotaryStartAngle);
1060     auto lineW = jmin (8.0f, radius * 0.5f);
1061     auto arcRadius = radius - lineW * 0.5f;
1062 
1063     Path backgroundArc;
1064     backgroundArc.addCentredArc (bounds.getCentreX(),
1065                                  bounds.getCentreY(),
1066                                  arcRadius,
1067                                  arcRadius,
1068                                  0.0f,
1069                                  rotaryStartAngle,
1070                                  rotaryEndAngle,
1071                                  true);
1072 
1073     g.setColour (outline);
1074     g.strokePath (backgroundArc, PathStrokeType (lineW, PathStrokeType::curved, PathStrokeType::rounded));
1075 
1076     if (slider.isEnabled())
1077     {
1078         Path valueArc;
1079         valueArc.addCentredArc (bounds.getCentreX(),
1080                                 bounds.getCentreY(),
1081                                 arcRadius,
1082                                 arcRadius,
1083                                 0.0f,
1084                                 rotaryStartAngle,
1085                                 toAngle,
1086                                 true);
1087 
1088         g.setColour (fill);
1089         g.strokePath (valueArc, PathStrokeType (lineW, PathStrokeType::curved, PathStrokeType::rounded));
1090     }
1091 
1092     auto thumbWidth = lineW * 2.0f;
1093     Point<float> thumbPoint (bounds.getCentreX() + arcRadius * std::cos (toAngle - MathConstants<float>::halfPi),
1094                              bounds.getCentreY() + arcRadius * std::sin (toAngle - MathConstants<float>::halfPi));
1095 
1096     g.setColour (slider.findColour (Slider::thumbColourId));
1097     g.fillEllipse (Rectangle<float> (thumbWidth, thumbWidth).withCentre (thumbPoint));
1098 }
1099 
drawPointer(Graphics & g,const float x,const float y,const float diameter,const Colour & colour,const int direction)1100 void LookAndFeel_V4::drawPointer (Graphics& g, const float x, const float y, const float diameter,
1101                                   const Colour& colour, const int direction) noexcept
1102 {
1103     Path p;
1104     p.startNewSubPath (x + diameter * 0.5f, y);
1105     p.lineTo (x + diameter, y + diameter * 0.6f);
1106     p.lineTo (x + diameter, y + diameter);
1107     p.lineTo (x, y + diameter);
1108     p.lineTo (x, y + diameter * 0.6f);
1109     p.closeSubPath();
1110 
1111     p.applyTransform (AffineTransform::rotation ((float) direction * MathConstants<float>::halfPi,
1112                                                  x + diameter * 0.5f, y + diameter * 0.5f));
1113     g.setColour (colour);
1114     g.fillPath (p);
1115 }
1116 
createSliderTextBox(Slider & slider)1117 Label* LookAndFeel_V4::createSliderTextBox (Slider& slider)
1118 {
1119     auto* l = LookAndFeel_V2::createSliderTextBox (slider);
1120 
1121     if (getCurrentColourScheme() == LookAndFeel_V4::getGreyColourScheme() && (slider.getSliderStyle() == Slider::LinearBar
1122                                                                                || slider.getSliderStyle() == Slider::LinearBarVertical))
1123     {
1124         l->setColour (Label::textColourId, Colours::black.withAlpha (0.7f));
1125     }
1126 
1127     return l;
1128 }
1129 
1130 //==============================================================================
drawTooltip(Graphics & g,const String & text,int width,int height)1131 void LookAndFeel_V4::drawTooltip (Graphics& g, const String& text, int width, int height)
1132 {
1133     Rectangle<int> bounds (width, height);
1134     auto cornerSize = 5.0f;
1135 
1136     g.setColour (findColour (TooltipWindow::backgroundColourId));
1137     g.fillRoundedRectangle (bounds.toFloat(), cornerSize);
1138 
1139     g.setColour (findColour (TooltipWindow::outlineColourId));
1140     g.drawRoundedRectangle (bounds.toFloat().reduced (0.5f, 0.5f), cornerSize, 1.0f);
1141 
1142     LookAndFeelHelpers::layoutTooltipText (text, findColour (TooltipWindow::textColourId))
1143                        .draw (g, { static_cast<float> (width), static_cast<float> (height) });
1144 }
1145 
1146 //==============================================================================
drawConcertinaPanelHeader(Graphics & g,const Rectangle<int> & area,bool isMouseOver,bool,ConcertinaPanel & concertina,Component & panel)1147 void LookAndFeel_V4::drawConcertinaPanelHeader (Graphics& g, const Rectangle<int>& area,
1148                                                 bool isMouseOver, bool /*isMouseDown*/,
1149                                                 ConcertinaPanel& concertina, Component& panel)
1150 {
1151     auto bounds = area.toFloat().reduced (0.5f);
1152     auto cornerSize = 4.0f;
1153     auto isTopPanel = (concertina.getPanel (0) == &panel);
1154 
1155     Path p;
1156     p.addRoundedRectangle (bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight(),
1157                            cornerSize, cornerSize, isTopPanel, isTopPanel, false, false);
1158 
1159     g.setGradientFill (ColourGradient::vertical (Colours::white.withAlpha (isMouseOver ? 0.4f : 0.2f), static_cast<float> (area.getY()),
1160                                                  Colours::darkgrey.withAlpha (0.1f), static_cast<float> (area.getBottom())));
1161     g.fillPath (p);
1162 }
1163 
1164 //==============================================================================
drawLevelMeter(Graphics & g,int width,int height,float level)1165 void LookAndFeel_V4::drawLevelMeter (Graphics& g, int width, int height, float level)
1166 {
1167     auto outerCornerSize = 3.0f;
1168     auto outerBorderWidth = 2.0f;
1169     auto totalBlocks = 7;
1170     auto spacingFraction = 0.03f;
1171 
1172     g.setColour (findColour (ResizableWindow::backgroundColourId));
1173     g.fillRoundedRectangle (0.0f, 0.0f, static_cast<float> (width), static_cast<float> (height), outerCornerSize);
1174 
1175     auto doubleOuterBorderWidth = 2.0f * outerBorderWidth;
1176     auto numBlocks = roundToInt ((float) totalBlocks * level);
1177 
1178     auto blockWidth = ((float) width - doubleOuterBorderWidth) / static_cast<float> (totalBlocks);
1179     auto blockHeight = (float) height - doubleOuterBorderWidth;
1180 
1181     auto blockRectWidth = (1.0f - 2.0f * spacingFraction) * blockWidth;
1182     auto blockRectSpacing = spacingFraction * blockWidth;
1183 
1184     auto blockCornerSize = 0.1f * blockWidth;
1185 
1186     auto c = findColour (Slider::thumbColourId);
1187 
1188     for (auto i = 0; i < totalBlocks; ++i)
1189     {
1190         if (i >= numBlocks)
1191             g.setColour (c.withAlpha (0.5f));
1192         else
1193             g.setColour (i < totalBlocks - 1 ? c : Colours::red);
1194 
1195         g.fillRoundedRectangle (outerBorderWidth + ((float) i * blockWidth) + blockRectSpacing,
1196                                 outerBorderWidth,
1197                                 blockRectWidth,
1198                                 blockHeight,
1199                                 blockCornerSize);
1200     }
1201 }
1202 
1203 //==============================================================================
paintToolbarBackground(Graphics & g,int w,int h,Toolbar & toolbar)1204 void LookAndFeel_V4::paintToolbarBackground (Graphics& g, int w, int h, Toolbar& toolbar)
1205 {
1206     auto background = toolbar.findColour (Toolbar::backgroundColourId);
1207 
1208     g.setGradientFill ({ background, 0.0f, 0.0f,
1209                          background.darker (0.2f),
1210                          toolbar.isVertical() ? (float) w - 1.0f : 0.0f,
1211                          toolbar.isVertical() ? 0.0f : (float) h - 1.0f,
1212                          false });
1213     g.fillAll();
1214 }
1215 
paintToolbarButtonLabel(Graphics & g,int x,int y,int width,int height,const String & text,ToolbarItemComponent & component)1216 void LookAndFeel_V4::paintToolbarButtonLabel (Graphics& g, int x, int y, int width, int height,
1217                                               const String& text, ToolbarItemComponent& component)
1218 {
1219     auto baseTextColour = component.findParentComponentOfClass<PopupMenu::CustomComponent>() != nullptr
1220                               ? component.findColour (PopupMenu::textColourId)
1221                               : component.findColour (Toolbar::labelTextColourId);
1222 
1223     g.setColour (baseTextColour.withAlpha (component.isEnabled() ? 1.0f : 0.25f));
1224 
1225     auto fontHeight = jmin (14.0f, (float) height * 0.85f);
1226     g.setFont (fontHeight);
1227 
1228     g.drawFittedText (text,
1229                       x, y, width, height,
1230                       Justification::centred,
1231                       jmax (1, height / (int) fontHeight));
1232 }
1233 
1234 //==============================================================================
drawPropertyPanelSectionHeader(Graphics & g,const String & name,bool isOpen,int width,int height)1235 void LookAndFeel_V4::drawPropertyPanelSectionHeader (Graphics& g, const String& name,
1236                                                      bool isOpen, int width, int height)
1237 {
1238     auto buttonSize = (float) height * 0.75f;
1239     auto buttonIndent = ((float) height - buttonSize) * 0.5f;
1240 
1241     drawTreeviewPlusMinusBox (g, { buttonIndent, buttonIndent, buttonSize, buttonSize },
1242                               findColour (ResizableWindow::backgroundColourId), isOpen, false);
1243 
1244     auto textX = static_cast<int> ((buttonIndent * 2.0f + buttonSize + 2.0f));
1245 
1246     g.setColour (findColour (PropertyComponent::labelTextColourId));
1247 
1248     g.setFont ({ (float) height * 0.7f, Font::bold });
1249     g.drawText (name, textX, 0, width - textX - 4, height, Justification::centredLeft, true);
1250 }
1251 
drawPropertyComponentBackground(Graphics & g,int width,int height,PropertyComponent & component)1252 void LookAndFeel_V4::drawPropertyComponentBackground (Graphics& g, int width, int height, PropertyComponent& component)
1253 {
1254     g.setColour (component.findColour (PropertyComponent::backgroundColourId));
1255     g.fillRect  (0, 0, width, height - 1);
1256 }
1257 
drawPropertyComponentLabel(Graphics & g,int width,int height,PropertyComponent & component)1258 void LookAndFeel_V4::drawPropertyComponentLabel (Graphics& g, int width, int height, PropertyComponent& component)
1259 {
1260     ignoreUnused (width);
1261 
1262     auto indent = getPropertyComponentIndent (component);
1263 
1264     g.setColour (component.findColour (PropertyComponent::labelTextColourId)
1265                           .withMultipliedAlpha (component.isEnabled() ? 1.0f : 0.6f));
1266 
1267     g.setFont ((float) jmin (height, 24) * 0.65f);
1268 
1269     auto r = getPropertyComponentContentPosition (component);
1270 
1271     g.drawFittedText (component.getName(),
1272                       indent, r.getY(), r.getX() - 5, r.getHeight(),
1273                       Justification::centredLeft, 2);
1274 }
1275 
getPropertyComponentIndent(PropertyComponent & component)1276 int LookAndFeel_V4::getPropertyComponentIndent (PropertyComponent& component)
1277 {
1278     return jmin (10, component.getWidth() / 10);
1279 }
1280 
getPropertyComponentContentPosition(PropertyComponent & component)1281 Rectangle<int> LookAndFeel_V4::getPropertyComponentContentPosition (PropertyComponent& component)
1282 {
1283     auto textW = jmin (200, component.getWidth() / 2);
1284     return { textW, 0, component.getWidth() - textW, component.getHeight() - 1 };
1285 }
1286 
1287 //==============================================================================
drawCallOutBoxBackground(CallOutBox & box,Graphics & g,const Path & path,Image & cachedImage)1288 void LookAndFeel_V4::drawCallOutBoxBackground (CallOutBox& box, Graphics& g,
1289                                                const Path& path, Image& cachedImage)
1290 {
1291     if (cachedImage.isNull())
1292     {
1293         cachedImage = { Image::ARGB, box.getWidth(), box.getHeight(), true };
1294         Graphics g2 (cachedImage);
1295 
1296         DropShadow (Colours::black.withAlpha (0.7f), 8, { 0, 2 }).drawForPath (g2, path);
1297     }
1298 
1299     g.setColour (Colours::black);
1300     g.drawImageAt (cachedImage, 0, 0);
1301 
1302     g.setColour (currentColourScheme.getUIColour (ColourScheme::UIColour::widgetBackground).withAlpha (0.8f));
1303     g.fillPath (path);
1304 
1305     g.setColour (currentColourScheme.getUIColour (ColourScheme::UIColour::outline).withAlpha (0.8f));
1306     g.strokePath (path, PathStrokeType (2.0f));
1307 }
1308 
1309 //==============================================================================
drawStretchableLayoutResizerBar(Graphics & g,int,int,bool,bool isMouseOver,bool isMouseDragging)1310 void LookAndFeel_V4::drawStretchableLayoutResizerBar (Graphics& g, int /*w*/, int /*h*/, bool /*isVerticalBar*/,
1311                                       bool isMouseOver, bool isMouseDragging)
1312 {
1313     if (isMouseOver || isMouseDragging)
1314         g.fillAll (currentColourScheme.getUIColour (ColourScheme::UIColour::defaultFill).withAlpha (0.5f));
1315 }
1316 
1317 //==============================================================================
initialiseColours()1318 void LookAndFeel_V4::initialiseColours()
1319 {
1320     const uint32 transparent = 0x00000000;
1321 
1322     const uint32 coloursToUse[] =
1323     {
1324         TextButton::buttonColourId,                 currentColourScheme.getUIColour (ColourScheme::UIColour::widgetBackground).getARGB(),
1325         TextButton::buttonOnColourId,               currentColourScheme.getUIColour (ColourScheme::UIColour::highlightedFill).getARGB(),
1326         TextButton::textColourOnId,                 currentColourScheme.getUIColour (ColourScheme::UIColour::highlightedText).getARGB(),
1327         TextButton::textColourOffId,                currentColourScheme.getUIColour (ColourScheme::UIColour::defaultText).getARGB(),
1328 
1329         ToggleButton::textColourId,                 currentColourScheme.getUIColour (ColourScheme::UIColour::defaultText).getARGB(),
1330         ToggleButton::tickColourId,                 currentColourScheme.getUIColour (ColourScheme::UIColour::defaultText).getARGB(),
1331         ToggleButton::tickDisabledColourId,         currentColourScheme.getUIColour (ColourScheme::UIColour::defaultText).withAlpha (0.5f).getARGB(),
1332 
1333         TextEditor::backgroundColourId,             currentColourScheme.getUIColour (ColourScheme::UIColour::widgetBackground).getARGB(),
1334         TextEditor::textColourId,                   currentColourScheme.getUIColour (ColourScheme::UIColour::defaultText).getARGB(),
1335         TextEditor::highlightColourId,              currentColourScheme.getUIColour (ColourScheme::UIColour::defaultFill).withAlpha (0.4f).getARGB(),
1336         TextEditor::highlightedTextColourId,        currentColourScheme.getUIColour (ColourScheme::UIColour::highlightedText).getARGB(),
1337         TextEditor::outlineColourId,                currentColourScheme.getUIColour (ColourScheme::UIColour::outline).getARGB(),
1338         TextEditor::focusedOutlineColourId,         currentColourScheme.getUIColour (ColourScheme::UIColour::outline).getARGB(),
1339         TextEditor::shadowColourId,                 transparent,
1340 
1341         CaretComponent::caretColourId,              currentColourScheme.getUIColour (ColourScheme::UIColour::defaultFill).getARGB(),
1342 
1343         Label::backgroundColourId,                  transparent,
1344         Label::textColourId,                        currentColourScheme.getUIColour (ColourScheme::UIColour::defaultText).getARGB(),
1345         Label::outlineColourId,                     transparent,
1346         Label::textWhenEditingColourId,             currentColourScheme.getUIColour (ColourScheme::UIColour::defaultText).getARGB(),
1347 
1348         ScrollBar::backgroundColourId,              transparent,
1349         ScrollBar::thumbColourId,                   currentColourScheme.getUIColour (ColourScheme::UIColour::defaultFill).getARGB(),
1350         ScrollBar::trackColourId,                   transparent,
1351 
1352         TreeView::linesColourId,                    transparent,
1353         TreeView::backgroundColourId,               transparent,
1354         TreeView::dragAndDropIndicatorColourId,     currentColourScheme.getUIColour (ColourScheme::UIColour::outline).getARGB(),
1355         TreeView::selectedItemBackgroundColourId,   transparent,
1356         TreeView::oddItemsColourId,                 transparent,
1357         TreeView::evenItemsColourId,                transparent,
1358 
1359         PopupMenu::backgroundColourId,              currentColourScheme.getUIColour (ColourScheme::UIColour::menuBackground).getARGB(),
1360         PopupMenu::textColourId,                    currentColourScheme.getUIColour (ColourScheme::UIColour::menuText).getARGB(),
1361         PopupMenu::headerTextColourId,              currentColourScheme.getUIColour (ColourScheme::UIColour::menuText).getARGB(),
1362         PopupMenu::highlightedTextColourId,         currentColourScheme.getUIColour (ColourScheme::UIColour::highlightedText).getARGB(),
1363         PopupMenu::highlightedBackgroundColourId,   currentColourScheme.getUIColour (ColourScheme::UIColour::highlightedFill).getARGB(),
1364 
1365         ComboBox::buttonColourId,                   currentColourScheme.getUIColour (ColourScheme::UIColour::outline).getARGB(),
1366         ComboBox::outlineColourId,                  currentColourScheme.getUIColour (ColourScheme::UIColour::outline).getARGB(),
1367         ComboBox::textColourId,                     currentColourScheme.getUIColour (ColourScheme::UIColour::defaultText).getARGB(),
1368         ComboBox::backgroundColourId,               currentColourScheme.getUIColour (ColourScheme::UIColour::widgetBackground).getARGB(),
1369         ComboBox::arrowColourId,                    currentColourScheme.getUIColour (ColourScheme::UIColour::defaultText).getARGB(),
1370         ComboBox::focusedOutlineColourId,           currentColourScheme.getUIColour (ColourScheme::UIColour::outline).getARGB(),
1371 
1372         PropertyComponent::backgroundColourId,      currentColourScheme.getUIColour (ColourScheme::UIColour::widgetBackground).getARGB(),
1373         PropertyComponent::labelTextColourId,       currentColourScheme.getUIColour (ColourScheme::UIColour::defaultText).getARGB(),
1374 
1375         TextPropertyComponent::backgroundColourId,  currentColourScheme.getUIColour (ColourScheme::UIColour::widgetBackground).getARGB(),
1376         TextPropertyComponent::textColourId,        currentColourScheme.getUIColour (ColourScheme::UIColour::defaultText).getARGB(),
1377         TextPropertyComponent::outlineColourId,     currentColourScheme.getUIColour (ColourScheme::UIColour::outline).getARGB(),
1378 
1379         BooleanPropertyComponent::backgroundColourId, currentColourScheme.getUIColour (ColourScheme::UIColour::widgetBackground).getARGB(),
1380         BooleanPropertyComponent::outlineColourId,    currentColourScheme.getUIColour (ColourScheme::UIColour::outline).getARGB(),
1381 
1382         ListBox::backgroundColourId,                currentColourScheme.getUIColour (ColourScheme::UIColour::widgetBackground).getARGB(),
1383         ListBox::outlineColourId,                   currentColourScheme.getUIColour (ColourScheme::UIColour::outline).getARGB(),
1384         ListBox::textColourId,                      currentColourScheme.getUIColour (ColourScheme::UIColour::defaultText).getARGB(),
1385 
1386         Slider::backgroundColourId,                 currentColourScheme.getUIColour (ColourScheme::UIColour::widgetBackground).getARGB(),
1387         Slider::thumbColourId,                      currentColourScheme.getUIColour (ColourScheme::UIColour::defaultFill).getARGB(),
1388         Slider::trackColourId,                      currentColourScheme.getUIColour (ColourScheme::UIColour::highlightedFill).getARGB(),
1389         Slider::rotarySliderFillColourId,           currentColourScheme.getUIColour (ColourScheme::UIColour::highlightedFill).getARGB(),
1390         Slider::rotarySliderOutlineColourId,        currentColourScheme.getUIColour (ColourScheme::UIColour::widgetBackground).getARGB(),
1391         Slider::textBoxTextColourId,                currentColourScheme.getUIColour (ColourScheme::UIColour::defaultText).getARGB(),
1392         Slider::textBoxBackgroundColourId,          currentColourScheme.getUIColour (ColourScheme::UIColour::widgetBackground).withAlpha (0.0f).getARGB(),
1393         Slider::textBoxHighlightColourId,           currentColourScheme.getUIColour (ColourScheme::UIColour::defaultFill).withAlpha (0.4f).getARGB(),
1394         Slider::textBoxOutlineColourId,             currentColourScheme.getUIColour (ColourScheme::UIColour::outline).getARGB(),
1395 
1396         ResizableWindow::backgroundColourId,        currentColourScheme.getUIColour (ColourScheme::UIColour::windowBackground).getARGB(),
1397 
1398         DocumentWindow::textColourId,               currentColourScheme.getUIColour (ColourScheme::UIColour::defaultText).getARGB(),
1399 
1400         AlertWindow::backgroundColourId,            currentColourScheme.getUIColour (ColourScheme::UIColour::widgetBackground).getARGB(),
1401         AlertWindow::textColourId,                  currentColourScheme.getUIColour (ColourScheme::UIColour::defaultText).getARGB(),
1402         AlertWindow::outlineColourId,               currentColourScheme.getUIColour (ColourScheme::UIColour::outline).getARGB(),
1403 
1404         ProgressBar::backgroundColourId,            currentColourScheme.getUIColour (ColourScheme::UIColour::widgetBackground).getARGB(),
1405         ProgressBar::foregroundColourId,            currentColourScheme.getUIColour (ColourScheme::UIColour::highlightedFill).getARGB(),
1406 
1407         TooltipWindow::backgroundColourId,          currentColourScheme.getUIColour (ColourScheme::UIColour::highlightedFill).getARGB(),
1408         TooltipWindow::textColourId,                currentColourScheme.getUIColour (ColourScheme::UIColour::highlightedText).getARGB(),
1409         TooltipWindow::outlineColourId,             transparent,
1410 
1411         TabbedComponent::backgroundColourId,        transparent,
1412         TabbedComponent::outlineColourId,           currentColourScheme.getUIColour (ColourScheme::UIColour::outline).getARGB(),
1413         TabbedButtonBar::tabOutlineColourId,        currentColourScheme.getUIColour (ColourScheme::UIColour::outline).withAlpha (0.5f).getARGB(),
1414         TabbedButtonBar::frontOutlineColourId,      currentColourScheme.getUIColour (ColourScheme::UIColour::outline).getARGB(),
1415 
1416         Toolbar::backgroundColourId,                currentColourScheme.getUIColour (ColourScheme::UIColour::widgetBackground).withAlpha (0.4f).getARGB(),
1417         Toolbar::separatorColourId,                 currentColourScheme.getUIColour (ColourScheme::UIColour::outline).getARGB(),
1418         Toolbar::buttonMouseOverBackgroundColourId, currentColourScheme.getUIColour (ColourScheme::UIColour::widgetBackground).contrasting (0.2f).getARGB(),
1419         Toolbar::buttonMouseDownBackgroundColourId, currentColourScheme.getUIColour (ColourScheme::UIColour::widgetBackground).contrasting (0.5f).getARGB(),
1420         Toolbar::labelTextColourId,                 currentColourScheme.getUIColour (ColourScheme::UIColour::defaultText).getARGB(),
1421         Toolbar::editingModeOutlineColourId,        currentColourScheme.getUIColour (ColourScheme::UIColour::outline).getARGB(),
1422 
1423         DrawableButton::textColourId,               currentColourScheme.getUIColour (ColourScheme::UIColour::defaultText).getARGB(),
1424         DrawableButton::textColourOnId,             currentColourScheme.getUIColour (ColourScheme::UIColour::highlightedText).getARGB(),
1425         DrawableButton::backgroundColourId,         transparent,
1426         DrawableButton::backgroundOnColourId,       currentColourScheme.getUIColour (ColourScheme::UIColour::highlightedFill).getARGB(),
1427 
1428         HyperlinkButton::textColourId,              currentColourScheme.getUIColour (ColourScheme::UIColour::defaultText).interpolatedWith (Colours::blue, 0.4f).getARGB(),
1429 
1430         GroupComponent::outlineColourId,            currentColourScheme.getUIColour (ColourScheme::UIColour::outline).getARGB(),
1431         GroupComponent::textColourId,               currentColourScheme.getUIColour (ColourScheme::UIColour::defaultText).getARGB(),
1432 
1433         BubbleComponent::backgroundColourId,        currentColourScheme.getUIColour (ColourScheme::UIColour::widgetBackground).getARGB(),
1434         BubbleComponent::outlineColourId,           currentColourScheme.getUIColour (ColourScheme::UIColour::outline).getARGB(),
1435 
1436         DirectoryContentsDisplayComponent::highlightColourId,          currentColourScheme.getUIColour (ColourScheme::UIColour::highlightedFill).getARGB(),
1437         DirectoryContentsDisplayComponent::textColourId,               currentColourScheme.getUIColour (ColourScheme::UIColour::menuText).getARGB(),
1438         DirectoryContentsDisplayComponent::highlightedTextColourId,    currentColourScheme.getUIColour (ColourScheme::UIColour::highlightedText).getARGB(),
1439 
1440         0x1000440, /*LassoComponent::lassoFillColourId*/        currentColourScheme.getUIColour (ColourScheme::UIColour::defaultFill).getARGB(),
1441         0x1000441, /*LassoComponent::lassoOutlineColourId*/     currentColourScheme.getUIColour (ColourScheme::UIColour::outline).getARGB(),
1442 
1443         0x1005000, /*MidiKeyboardComponent::whiteNoteColourId*/               0xffffffff,
1444         0x1005001, /*MidiKeyboardComponent::blackNoteColourId*/               0xff000000,
1445         0x1005002, /*MidiKeyboardComponent::keySeparatorLineColourId*/        0x66000000,
1446         0x1005003, /*MidiKeyboardComponent::mouseOverKeyOverlayColourId*/     0x80ffff00,
1447         0x1005004, /*MidiKeyboardComponent::keyDownOverlayColourId*/          0xffb6b600,
1448         0x1005005, /*MidiKeyboardComponent::textLabelColourId*/               0xff000000,
1449         0x1005006, /*MidiKeyboardComponent::upDownButtonBackgroundColourId*/  0xffd3d3d3,
1450         0x1005007, /*MidiKeyboardComponent::upDownButtonArrowColourId*/       0xff000000,
1451         0x1005008, /*MidiKeyboardComponent::shadowColourId*/                  0x4c000000,
1452 
1453         0x1004500, /*CodeEditorComponent::backgroundColourId*/                currentColourScheme.getUIColour (ColourScheme::UIColour::widgetBackground).getARGB(),
1454         0x1004502, /*CodeEditorComponent::highlightColourId*/                 currentColourScheme.getUIColour (ColourScheme::UIColour::defaultFill).withAlpha (0.4f).getARGB(),
1455         0x1004503, /*CodeEditorComponent::defaultTextColourId*/               currentColourScheme.getUIColour (ColourScheme::UIColour::defaultText).getARGB(),
1456         0x1004504, /*CodeEditorComponent::lineNumberBackgroundId*/            currentColourScheme.getUIColour (ColourScheme::UIColour::highlightedFill).withAlpha (0.5f).getARGB(),
1457         0x1004505, /*CodeEditorComponent::lineNumberTextId*/                  currentColourScheme.getUIColour (ColourScheme::UIColour::defaultFill).getARGB(),
1458 
1459         0x1007000, /*ColourSelector::backgroundColourId*/                     currentColourScheme.getUIColour (ColourScheme::UIColour::widgetBackground).getARGB(),
1460         0x1007001, /*ColourSelector::labelTextColourId*/                      currentColourScheme.getUIColour (ColourScheme::UIColour::defaultText).getARGB(),
1461 
1462         0x100ad00, /*KeyMappingEditorComponent::backgroundColourId*/          currentColourScheme.getUIColour (ColourScheme::UIColour::widgetBackground).getARGB(),
1463         0x100ad01, /*KeyMappingEditorComponent::textColourId*/                currentColourScheme.getUIColour (ColourScheme::UIColour::defaultText).getARGB(),
1464 
1465         FileSearchPathListComponent::backgroundColourId,        currentColourScheme.getUIColour (ColourScheme::UIColour::menuBackground).getARGB(),
1466 
1467         FileChooserDialogBox::titleTextColourId,                currentColourScheme.getUIColour (ColourScheme::UIColour::defaultText).getARGB(),
1468 
1469         SidePanel::backgroundColour,                            currentColourScheme.getUIColour (ColourScheme::UIColour::widgetBackground).getARGB(),
1470         SidePanel::titleTextColour,                             currentColourScheme.getUIColour (ColourScheme::UIColour::defaultText).getARGB(),
1471         SidePanel::shadowBaseColour,                            currentColourScheme.getUIColour (ColourScheme::UIColour::widgetBackground).darker().getARGB(),
1472         SidePanel::dismissButtonNormalColour,                   currentColourScheme.getUIColour (ColourScheme::UIColour::defaultFill).getARGB(),
1473         SidePanel::dismissButtonOverColour,                     currentColourScheme.getUIColour (ColourScheme::UIColour::defaultFill).darker().getARGB(),
1474         SidePanel::dismissButtonDownColour,                     currentColourScheme.getUIColour (ColourScheme::UIColour::defaultFill).brighter().getARGB(),
1475 
1476         FileBrowserComponent::currentPathBoxBackgroundColourId,    currentColourScheme.getUIColour (ColourScheme::UIColour::menuBackground).getARGB(),
1477         FileBrowserComponent::currentPathBoxTextColourId,          currentColourScheme.getUIColour (ColourScheme::UIColour::menuText).getARGB(),
1478         FileBrowserComponent::currentPathBoxArrowColourId,         currentColourScheme.getUIColour (ColourScheme::UIColour::menuText).getARGB(),
1479         FileBrowserComponent::filenameBoxBackgroundColourId,       currentColourScheme.getUIColour (ColourScheme::UIColour::menuBackground).getARGB(),
1480         FileBrowserComponent::filenameBoxTextColourId,             currentColourScheme.getUIColour (ColourScheme::UIColour::menuText).getARGB(),
1481     };
1482 
1483     for (int i = 0; i < numElementsInArray (coloursToUse); i += 2)
1484         setColour ((int) coloursToUse [i], Colour ((uint32) coloursToUse [i + 1]));
1485 }
1486 
1487 } // namespace juce
1488