2 ==============================================================================
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
7 JUCE is an open source library subject to commercial or open-source
10 By using JUCE, you agree to the terms of both the JUCE 7 End-User License
11 Agreement and JUCE Privacy Policy.
13 End User License Agreement: www.juce.com/juce-7-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
23 ==============================================================================
29 Colour
LookAndFeel_V4::ColourScheme::getUIColour (UIColour index
) const noexcept
31 if (isPositiveAndBelow (index
, numColours
))
32 return palette
[index
];
38 void LookAndFeel_V4::ColourScheme::setUIColour (UIColour index
, Colour newColour
) noexcept
40 if (isPositiveAndBelow (index
, numColours
))
41 palette
[index
] = newColour
;
46 bool LookAndFeel_V4::ColourScheme::operator== (const ColourScheme
& other
) const noexcept
48 for (auto i
= 0; i
< numColours
; ++i
)
49 if (palette
[i
] != other
.palette
[i
])
55 bool LookAndFeel_V4::ColourScheme::operator!= (const ColourScheme
& other
) const noexcept
57 return ! operator== (other
);
60 //==============================================================================
61 LookAndFeel_V4::LookAndFeel_V4() : currentColourScheme (getDarkColourScheme())
66 LookAndFeel_V4::LookAndFeel_V4 (ColourScheme scheme
) : currentColourScheme (scheme
)
71 LookAndFeel_V4::~LookAndFeel_V4() {}
73 //==============================================================================
74 void LookAndFeel_V4::setColourScheme (ColourScheme newColourScheme
)
76 currentColourScheme
= newColourScheme
;
80 LookAndFeel_V4::ColourScheme
LookAndFeel_V4::getDarkColourScheme()
82 return { 0xff323e44, 0xff263238, 0xff323e44,
83 0xff8e989b, 0xffffffff, 0xff42a2c8,
84 0xffffffff, 0xff181f22, 0xffffffff };
87 LookAndFeel_V4::ColourScheme
LookAndFeel_V4::getMidnightColourScheme()
89 return { 0xff2f2f3a, 0xff191926, 0xffd0d0d0,
90 0xff66667c, 0xc8ffffff, 0xffd8d8d8,
91 0xffffffff, 0xff606073, 0xff000000 };
94 LookAndFeel_V4::ColourScheme
LookAndFeel_V4::getGreyColourScheme()
96 return { 0xff505050, 0xff424242, 0xff606060,
97 0xffa6a6a6, 0xffffffff, 0xff21ba90,
98 0xff000000, 0xffffffff, 0xffffffff };
101 LookAndFeel_V4::ColourScheme
LookAndFeel_V4::getLightColourScheme()
103 return { 0xffefefef, 0xffffffff, 0xffffffff,
104 0xffdddddd, 0xff000000, 0xffa9a9a9,
105 0xffffffff, 0xff42a2c8, 0xff000000 };
108 //==============================================================================
109 class LookAndFeel_V4_DocumentWindowButton
: public Button
112 LookAndFeel_V4_DocumentWindowButton (const String
& name
, Colour c
, const Path
& normal
, const Path
& toggled
)
113 : Button (name
), colour (c
), normalShape (normal
), toggledShape (toggled
)
117 void paintButton (Graphics
& g
, bool shouldDrawButtonAsHighlighted
, bool shouldDrawButtonAsDown
) override
119 auto background
= Colours::grey
;
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
);
125 g
.fillAll (background
);
127 g
.setColour ((! isEnabled() || shouldDrawButtonAsDown
) ? colour
.withAlpha (0.6f
)
130 if (shouldDrawButtonAsHighlighted
)
133 g
.setColour (background
);
136 auto& p
= getToggleState() ? toggledShape
: normalShape
;
138 auto reducedRect
= Justification (Justification::centred
)
139 .appliedToRectangle (Rectangle
<int> (getHeight(), getHeight()), getLocalBounds())
141 .reduced ((float) getHeight() * 0.3f
);
143 g
.fillPath (p
, p
.getTransformToScaleToFit (reducedRect
, true));
148 Path normalShape
, toggledShape
;
150 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LookAndFeel_V4_DocumentWindowButton
)
153 Button
* LookAndFeel_V4::createDocumentWindowButton (int buttonType
)
156 auto crossThickness
= 0.15f
;
158 if (buttonType
== DocumentWindow::closeButton
)
160 shape
.addLineSegment ({ 0.0f
, 0.0f
, 1.0f
, 1.0f
}, crossThickness
);
161 shape
.addLineSegment ({ 1.0f
, 0.0f
, 0.0f
, 1.0f
}, crossThickness
);
163 return new LookAndFeel_V4_DocumentWindowButton ("close", Colour (0xff9A131D), shape
, shape
);
166 if (buttonType
== DocumentWindow::minimiseButton
)
168 shape
.addLineSegment ({ 0.0f
, 0.5f
, 1.0f
, 0.5f
}, crossThickness
);
170 return new LookAndFeel_V4_DocumentWindowButton ("minimise", Colour (0xffaa8811), shape
, shape
);
173 if (buttonType
== DocumentWindow::maximiseButton
)
175 shape
.addLineSegment ({ 0.5f
, 0.0f
, 0.5f
, 1.0f
}, crossThickness
);
176 shape
.addLineSegment ({ 0.0f
, 0.5f
, 1.0f
, 0.5f
}, crossThickness
);
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
);
187 return new LookAndFeel_V4_DocumentWindowButton ("maximise", Colour (0xff0A830A), shape
, fullscreenShape
);
194 void LookAndFeel_V4::positionDocumentWindowButtons (DocumentWindow
&,
195 int titleBarX
, int titleBarY
,
196 int titleBarW
, int titleBarH
,
197 Button
* minimiseButton
,
198 Button
* maximiseButton
,
200 bool positionTitleBarButtonsOnLeft
)
202 auto buttonW
= static_cast<int> (titleBarH
* 1.2);
204 auto x
= positionTitleBarButtonsOnLeft
? titleBarX
205 : titleBarX
+ titleBarW
- buttonW
;
207 if (closeButton
!= nullptr)
209 closeButton
->setBounds (x
, titleBarY
, buttonW
, titleBarH
);
210 x
+= positionTitleBarButtonsOnLeft
? buttonW
: -buttonW
;
213 if (positionTitleBarButtonsOnLeft
)
214 std::swap (minimiseButton
, maximiseButton
);
216 if (maximiseButton
!= nullptr)
218 maximiseButton
->setBounds (x
, titleBarY
, buttonW
, titleBarH
);
219 x
+= positionTitleBarButtonsOnLeft
? buttonW
: -buttonW
;
222 if (minimiseButton
!= nullptr)
223 minimiseButton
->setBounds (x
, titleBarY
, buttonW
, titleBarH
);
226 void LookAndFeel_V4::drawDocumentWindowTitleBar (DocumentWindow
& window
, Graphics
& g
,
227 int w
, int h
, int titleSpaceX
, int titleSpaceW
,
228 const Image
* icon
, bool drawTitleTextOnLeft
)
233 auto isActive
= window
.isActiveWindow();
235 g
.setColour (getCurrentColourScheme().getUIColour (ColourScheme::widgetBackground
));
238 Font
font ((float) h
* 0.65f
, Font::plain
);
241 auto textW
= font
.getStringWidth (window
.getName());
247 iconH
= static_cast<int> (font
.getHeight());
248 iconW
= icon
->getWidth() * iconH
/ icon
->getHeight() + 4;
251 textW
= jmin (titleSpaceW
, textW
+ iconW
);
252 auto textX
= drawTitleTextOnLeft
? titleSpaceX
253 : jmax (titleSpaceX
, (w
- textW
) / 2);
255 if (textX
+ textW
> titleSpaceX
+ titleSpaceW
)
256 textX
= titleSpaceX
+ titleSpaceW
- textW
;
260 g
.setOpacity (isActive
? 1.0f
: 0.6f
);
261 g
.drawImageWithin (*icon
, textX
, (h
- iconH
) / 2, iconW
, iconH
,
262 RectanglePlacement::centred
, false);
267 if (window
.isColourSpecified (DocumentWindow::textColourId
) || isColourSpecified (DocumentWindow::textColourId
))
268 g
.setColour (window
.findColour (DocumentWindow::textColourId
));
270 g
.setColour (getCurrentColourScheme().getUIColour (ColourScheme::defaultText
));
272 g
.drawText (window
.getName(), textX
, 0, textW
, h
, Justification::centredLeft
, true);
275 //==============================================================================
276 Font
LookAndFeel_V4::getTextButtonFont (TextButton
&, int buttonHeight
)
278 return { jmin (16.0f
, (float) buttonHeight
* 0.6f
) };
281 void LookAndFeel_V4::drawButtonBackground (Graphics
& g
,
283 const Colour
& backgroundColour
,
284 bool shouldDrawButtonAsHighlighted
,
285 bool shouldDrawButtonAsDown
)
287 auto cornerSize
= 6.0f
;
288 auto bounds
= button
.getLocalBounds().toFloat().reduced (0.5f
, 0.5f
);
290 auto baseColour
= backgroundColour
.withMultipliedSaturation (button
.hasKeyboardFocus (true) ? 1.3f
: 0.9f
)
291 .withMultipliedAlpha (button
.isEnabled() ? 1.0f
: 0.5f
);
293 if (shouldDrawButtonAsDown
|| shouldDrawButtonAsHighlighted
)
294 baseColour
= baseColour
.contrasting (shouldDrawButtonAsDown
? 0.2f
: 0.05f
);
296 g
.setColour (baseColour
);
298 auto flatOnLeft
= button
.isConnectedOnLeft();
299 auto flatOnRight
= button
.isConnectedOnRight();
300 auto flatOnTop
= button
.isConnectedOnTop();
301 auto flatOnBottom
= button
.isConnectedOnBottom();
303 if (flatOnLeft
|| flatOnRight
|| flatOnTop
|| flatOnBottom
)
306 path
.addRoundedRectangle (bounds
.getX(), bounds
.getY(),
307 bounds
.getWidth(), bounds
.getHeight(),
308 cornerSize
, cornerSize
,
309 ! (flatOnLeft
|| flatOnTop
),
310 ! (flatOnRight
|| flatOnTop
),
311 ! (flatOnLeft
|| flatOnBottom
),
312 ! (flatOnRight
|| flatOnBottom
));
316 g
.setColour (button
.findColour (ComboBox::outlineColourId
));
317 g
.strokePath (path
, PathStrokeType (1.0f
));
321 g
.fillRoundedRectangle (bounds
, cornerSize
);
323 g
.setColour (button
.findColour (ComboBox::outlineColourId
));
324 g
.drawRoundedRectangle (bounds
, cornerSize
, 1.0f
);
328 void LookAndFeel_V4::drawToggleButton (Graphics
& g
, ToggleButton
& button
,
329 bool shouldDrawButtonAsHighlighted
, bool shouldDrawButtonAsDown
)
331 auto fontSize
= jmin (15.0f
, (float) button
.getHeight() * 0.75f
);
332 auto tickWidth
= fontSize
* 1.1f
;
334 drawTickBox (g
, button
, 4.0f
, ((float) button
.getHeight() - tickWidth
) * 0.5f
,
335 tickWidth
, tickWidth
,
336 button
.getToggleState(),
338 shouldDrawButtonAsHighlighted
,
339 shouldDrawButtonAsDown
);
341 g
.setColour (button
.findColour (ToggleButton::textColourId
));
342 g
.setFont (fontSize
);
344 if (! button
.isEnabled())
347 g
.drawFittedText (button
.getButtonText(),
348 button
.getLocalBounds().withTrimmedLeft (roundToInt (tickWidth
) + 10)
349 .withTrimmedRight (2),
350 Justification::centredLeft
, 10);
353 void LookAndFeel_V4::drawTickBox (Graphics
& g
, Component
& component
,
354 float x
, float y
, float w
, float h
,
356 const bool isEnabled
,
357 const bool shouldDrawButtonAsHighlighted
,
358 const bool shouldDrawButtonAsDown
)
360 ignoreUnused (isEnabled
, shouldDrawButtonAsHighlighted
, shouldDrawButtonAsDown
);
362 Rectangle
<float> tickBounds (x
, y
, w
, h
);
364 g
.setColour (component
.findColour (ToggleButton::tickDisabledColourId
));
365 g
.drawRoundedRectangle (tickBounds
, 4.0f
, 1.0f
);
369 g
.setColour (component
.findColour (ToggleButton::tickColourId
));
370 auto tick
= getTickShape (0.75f
);
371 g
.fillPath (tick
, tick
.getTransformToScaleToFit (tickBounds
.reduced (4, 5).toFloat(), false));
375 void LookAndFeel_V4::changeToggleButtonWidthToFitText (ToggleButton
& button
)
377 auto fontSize
= jmin (15.0f
, (float) button
.getHeight() * 0.75f
);
378 auto tickWidth
= fontSize
* 1.1f
;
380 Font
font (fontSize
);
382 button
.setSize (font
.getStringWidth (button
.getButtonText()) + roundToInt (tickWidth
) + 14, button
.getHeight());
385 //==============================================================================
386 AlertWindow
* LookAndFeel_V4::createAlertWindow (const String
& title
, const String
& message
,
387 const String
& button1
, const String
& button2
, const String
& button3
,
388 MessageBoxIconType iconType
,
389 int numButtons
, Component
* associatedComponent
)
391 auto boundsOffset
= 50;
393 auto* aw
= LookAndFeel_V2::createAlertWindow (title
, message
, button1
, button2
, button3
,
394 iconType
, numButtons
, associatedComponent
);
396 auto bounds
= aw
->getBounds();
397 bounds
= bounds
.withSizeKeepingCentre (bounds
.getWidth() + boundsOffset
, bounds
.getHeight() + boundsOffset
);
398 aw
->setBounds (bounds
);
400 for (auto* child
: aw
->getChildren())
401 if (auto* button
= dynamic_cast<TextButton
*> (child
))
402 button
->setBounds (button
->getBounds() + Point
<int> (25, 40));
407 void LookAndFeel_V4::drawAlertBox (Graphics
& g
, AlertWindow
& alert
,
408 const Rectangle
<int>& textArea
, TextLayout
& textLayout
)
410 auto cornerSize
= 4.0f
;
412 g
.setColour (alert
.findColour (AlertWindow::outlineColourId
));
413 g
.drawRoundedRectangle (alert
.getLocalBounds().toFloat(), cornerSize
, 2.0f
);
415 auto bounds
= alert
.getLocalBounds().reduced (1);
416 g
.reduceClipRegion (bounds
);
418 g
.setColour (alert
.findColour (AlertWindow::backgroundColourId
));
419 g
.fillRoundedRectangle (bounds
.toFloat(), cornerSize
);
421 auto iconSpaceUsed
= 0;
424 auto iconSize
= jmin (iconWidth
+ 50, bounds
.getHeight() + 20);
426 if (alert
.containsAnyExtraComponents() || alert
.getNumButtons() > 2)
427 iconSize
= jmin (iconSize
, textArea
.getHeight() + 50);
429 Rectangle
<int> iconRect (iconSize
/ -10, iconSize
/ -10,
432 if (alert
.getAlertType() != MessageBoxIconType::NoIcon
)
438 if (alert
.getAlertType() == MessageBoxIconType::WarningIcon
)
442 icon
.addTriangle ((float) iconRect
.getX() + (float) iconRect
.getWidth() * 0.5f
, (float) iconRect
.getY(),
443 static_cast<float> (iconRect
.getRight()), static_cast<float> (iconRect
.getBottom()),
444 static_cast<float> (iconRect
.getX()), static_cast<float> (iconRect
.getBottom()));
446 icon
= icon
.createPathWithRoundedCorners (5.0f
);
451 colour
= Colour (0xff00b0b9).withAlpha (0.4f
).getARGB();
452 character
= alert
.getAlertType() == MessageBoxIconType::InfoIcon
? 'i' : '?';
454 icon
.addEllipse (iconRect
.toFloat());
458 ga
.addFittedText ({ (float) iconRect
.getHeight() * 0.9f
, Font::bold
},
459 String::charToString ((juce_wchar
) (uint8
) character
),
460 static_cast<float> (iconRect
.getX()), static_cast<float> (iconRect
.getY()),
461 static_cast<float> (iconRect
.getWidth()), static_cast<float> (iconRect
.getHeight()),
462 Justification::centred
, false);
463 ga
.createPath (icon
);
465 icon
.setUsingNonZeroWinding (false);
466 g
.setColour (Colour (colour
));
469 iconSpaceUsed
= iconWidth
;
472 g
.setColour (alert
.findColour (AlertWindow::textColourId
));
474 Rectangle
<int> alertBounds (bounds
.getX() + iconSpaceUsed
, 30,
475 bounds
.getWidth(), bounds
.getHeight() - getAlertWindowButtonHeight() - 20);
477 textLayout
.draw (g
, alertBounds
.toFloat());
480 int LookAndFeel_V4::getAlertWindowButtonHeight() { return 40; }
481 Font
LookAndFeel_V4::getAlertWindowTitleFont() { return { 18.0f
, Font::bold
}; }
482 Font
LookAndFeel_V4::getAlertWindowMessageFont() { return { 16.0f
}; }
483 Font
LookAndFeel_V4::getAlertWindowFont() { return { 14.0f
}; }
485 //==============================================================================
486 void LookAndFeel_V4::drawProgressBar (Graphics
& g
, ProgressBar
& progressBar
,
487 int width
, int height
, double progress
, const String
& textToShow
)
490 drawCircularProgressBar (g
, progressBar
, textToShow
);
492 drawLinearProgressBar (g
, progressBar
, width
, height
, progress
, textToShow
);
495 void LookAndFeel_V4::drawLinearProgressBar (Graphics
& g
, ProgressBar
& progressBar
,
496 int width
, int height
,
497 double progress
, const String
& textToShow
)
499 auto background
= progressBar
.findColour (ProgressBar::backgroundColourId
);
500 auto foreground
= progressBar
.findColour (ProgressBar::foregroundColourId
);
502 auto barBounds
= progressBar
.getLocalBounds().toFloat();
504 g
.setColour (background
);
505 g
.fillRoundedRectangle (barBounds
, (float) progressBar
.getHeight() * 0.5f
);
507 if (progress
>= 0.0f
&& progress
<= 1.0f
)
510 p
.addRoundedRectangle (barBounds
, (float) progressBar
.getHeight() * 0.5f
);
511 g
.reduceClipRegion (p
);
513 barBounds
.setWidth (barBounds
.getWidth() * (float) progress
);
514 g
.setColour (foreground
);
515 g
.fillRoundedRectangle (barBounds
, (float) progressBar
.getHeight() * 0.5f
);
520 g
.setColour (background
);
522 auto stripeWidth
= height
* 2;
523 auto position
= static_cast<int> (Time::getMillisecondCounter() / 15) % stripeWidth
;
527 for (auto x
= static_cast<float> (-position
); x
< (float) (width
+ stripeWidth
); x
+= (float) stripeWidth
)
528 p
.addQuadrilateral (x
, 0.0f
,
529 x
+ (float) stripeWidth
* 0.5f
, 0.0f
,
530 x
, static_cast<float> (height
),
531 x
- (float) stripeWidth
* 0.5f
, static_cast<float> (height
));
533 Image
im (Image::ARGB
, width
, height
, true);
537 g2
.setColour (foreground
);
538 g2
.fillRoundedRectangle (barBounds
, (float) progressBar
.getHeight() * 0.5f
);
541 g
.setTiledImageFill (im
, 0, 0, 0.85f
);
545 if (textToShow
.isNotEmpty())
547 g
.setColour (Colour::contrasting (background
, foreground
));
548 g
.setFont ((float) height
* 0.6f
);
550 g
.drawText (textToShow
, 0, 0, width
, height
, Justification::centred
, false);
554 void LookAndFeel_V4::drawCircularProgressBar (Graphics
& g
, ProgressBar
& progressBar
, const String
& progressText
)
556 auto background
= progressBar
.findColour (ProgressBar::backgroundColourId
);
557 auto foreground
= progressBar
.findColour (ProgressBar::foregroundColourId
);
559 auto barBounds
= progressBar
.getLocalBounds().reduced (2, 2).toFloat();
561 auto rotationInDegrees
= static_cast<float> ((Time::getMillisecondCounter() / 10) % 360);
562 auto normalisedRotation
= rotationInDegrees
/ 360.0f
;
564 auto rotationOffset
= 22.5f
;
565 auto maxRotation
= 315.0f
;
567 auto startInDegrees
= rotationInDegrees
;
568 auto endInDegrees
= startInDegrees
+ rotationOffset
;
570 if (normalisedRotation
>= 0.25f
&& normalisedRotation
< 0.5f
)
572 auto rescaledRotation
= (normalisedRotation
* 4.0f
) - 1.0f
;
573 endInDegrees
= startInDegrees
+ rotationOffset
+ (maxRotation
* rescaledRotation
);
575 else if (normalisedRotation
>= 0.5f
&& normalisedRotation
<= 1.0f
)
577 endInDegrees
= startInDegrees
+ rotationOffset
+ maxRotation
;
578 auto rescaledRotation
= 1.0f
- ((normalisedRotation
* 2.0f
) - 1.0f
);
579 startInDegrees
= endInDegrees
- rotationOffset
- (maxRotation
* rescaledRotation
);
582 g
.setColour (background
);
584 arcPath2
.addCentredArc (barBounds
.getCentreX(),
585 barBounds
.getCentreY(),
586 barBounds
.getWidth() * 0.5f
,
587 barBounds
.getHeight() * 0.5f
, 0.0f
,
589 MathConstants
<float>::twoPi
,
591 g
.strokePath (arcPath2
, PathStrokeType (4.0f
));
593 g
.setColour (foreground
);
595 arcPath
.addCentredArc (barBounds
.getCentreX(),
596 barBounds
.getCentreY(),
597 barBounds
.getWidth() * 0.5f
,
598 barBounds
.getHeight() * 0.5f
,
600 degreesToRadians (startInDegrees
),
601 degreesToRadians (endInDegrees
),
604 arcPath
.applyTransform (AffineTransform::rotation (normalisedRotation
* MathConstants
<float>::pi
* 2.25f
, barBounds
.getCentreX(), barBounds
.getCentreY()));
605 g
.strokePath (arcPath
, PathStrokeType (4.0f
));
607 if (progressText
.isNotEmpty())
609 g
.setColour (progressBar
.findColour (TextButton::textColourOffId
));
610 g
.setFont ({ 12.0f
, Font::italic
});
611 g
.drawText (progressText
, barBounds
, Justification::centred
, false);
615 //==============================================================================
616 int LookAndFeel_V4::getDefaultScrollbarWidth()
621 void LookAndFeel_V4::drawScrollbar (Graphics
& g
, ScrollBar
& scrollbar
, int x
, int y
, int width
, int height
,
622 bool isScrollbarVertical
, int thumbStartPosition
, int thumbSize
, bool isMouseOver
, bool isMouseDown
)
624 ignoreUnused (isMouseDown
);
626 Rectangle
<int> thumbBounds
;
628 if (isScrollbarVertical
)
629 thumbBounds
= { x
, thumbStartPosition
, width
, thumbSize
};
631 thumbBounds
= { thumbStartPosition
, y
, thumbSize
, height
};
633 auto c
= scrollbar
.findColour (ScrollBar::ColourIds::thumbColourId
);
634 g
.setColour (isMouseOver
? c
.brighter (0.25f
) : c
);
635 g
.fillRoundedRectangle (thumbBounds
.reduced (1).toFloat(), 4.0f
);
638 //==============================================================================
639 Path
LookAndFeel_V4::getTickShape (float height
)
641 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,
642 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 path
.loadPathFromData (pathData
, sizeof (pathData
));
646 path
.scaleToFit (0, 0, height
* 2.0f
, height
, true);
651 Path
LookAndFeel_V4::getCrossShape (float height
)
653 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,
654 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,
655 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 path
.loadPathFromData (pathData
, sizeof (pathData
));
659 path
.scaleToFit (0, 0, height
* 2.0f
, height
, true);
664 //==============================================================================
665 void LookAndFeel_V4::fillTextEditorBackground (Graphics
& g
, int width
, int height
, TextEditor
& textEditor
)
667 if (dynamic_cast<AlertWindow
*> (textEditor
.getParentComponent()) != nullptr)
669 g
.setColour (textEditor
.findColour (TextEditor::backgroundColourId
));
670 g
.fillRect (0, 0, width
, height
);
672 g
.setColour (textEditor
.findColour (TextEditor::outlineColourId
));
673 g
.drawHorizontalLine (height
- 1, 0.0f
, static_cast<float> (width
));
677 LookAndFeel_V2::fillTextEditorBackground (g
, width
, height
, textEditor
);
681 void LookAndFeel_V4::drawTextEditorOutline (Graphics
& g
, int width
, int height
, TextEditor
& textEditor
)
683 if (dynamic_cast<AlertWindow
*> (textEditor
.getParentComponent()) == nullptr)
685 if (textEditor
.isEnabled())
687 if (textEditor
.hasKeyboardFocus (true) && ! textEditor
.isReadOnly())
689 g
.setColour (textEditor
.findColour (TextEditor::focusedOutlineColourId
));
690 g
.drawRect (0, 0, width
, height
, 2);
694 g
.setColour (textEditor
.findColour (TextEditor::outlineColourId
));
695 g
.drawRect (0, 0, width
, height
);
701 //==============================================================================
702 Button
* LookAndFeel_V4::createFileBrowserGoUpButton()
704 auto* goUpButton
= new DrawableButton ("up", DrawableButton::ImageOnButtonBackground
);
707 arrowPath
.addArrow ({ 50.0f
, 100.0f
, 50.0f
, 0.0f
}, 40.0f
, 100.0f
, 50.0f
);
709 DrawablePath arrowImage
;
710 arrowImage
.setFill (goUpButton
->findColour (TextButton::textColourOffId
));
711 arrowImage
.setPath (arrowPath
);
713 goUpButton
->setImages (&arrowImage
);
718 void LookAndFeel_V4::layoutFileBrowserComponent (FileBrowserComponent
& browserComp
,
719 DirectoryContentsDisplayComponent
* fileListComponent
,
720 FilePreviewComponent
* previewComp
,
721 ComboBox
* currentPathBox
,
722 TextEditor
* filenameBox
,
725 auto sectionHeight
= 22;
726 auto buttonWidth
= 50;
728 auto b
= browserComp
.getLocalBounds().reduced (20, 5);
730 auto topSlice
= b
.removeFromTop (sectionHeight
);
731 auto bottomSlice
= b
.removeFromBottom (sectionHeight
);
733 currentPathBox
->setBounds (topSlice
.removeFromLeft (topSlice
.getWidth() - buttonWidth
));
735 topSlice
.removeFromLeft (6);
736 goUpButton
->setBounds (topSlice
);
738 bottomSlice
.removeFromLeft (20);
739 filenameBox
->setBounds (bottomSlice
);
741 if (previewComp
!= nullptr)
742 previewComp
->setBounds (b
.removeFromRight (b
.getWidth() / 3));
744 if (auto* listAsComp
= dynamic_cast<Component
*> (fileListComponent
))
745 listAsComp
->setBounds (b
.reduced (0, 10));
748 void LookAndFeel_V4::drawFileBrowserRow (Graphics
& g
, int width
, int height
,
749 const File
& file
, const String
& filename
, Image
* icon
,
750 const String
& fileSizeDescription
,
751 const String
& fileTimeDescription
,
752 bool isDirectory
, bool isItemSelected
,
753 int itemIndex
, DirectoryContentsDisplayComponent
& dcc
)
755 LookAndFeel_V2::drawFileBrowserRow (g
, width
, height
, file
, filename
, icon
,
756 fileSizeDescription
, fileTimeDescription
,
757 isDirectory
, isItemSelected
, itemIndex
, dcc
);
760 //==============================================================================
761 void LookAndFeel_V4::drawPopupMenuItem (Graphics
& g
, const Rectangle
<int>& area
,
762 const bool isSeparator
, const bool isActive
,
763 const bool isHighlighted
, const bool isTicked
,
764 const bool hasSubMenu
, const String
& text
,
765 const String
& shortcutKeyText
,
766 const Drawable
* icon
, const Colour
* const textColourToUse
)
770 auto r
= area
.reduced (5, 0);
771 r
.removeFromTop (roundToInt (((float) r
.getHeight() * 0.5f
) - 0.5f
));
773 g
.setColour (findColour (PopupMenu::textColourId
).withAlpha (0.3f
));
774 g
.fillRect (r
.removeFromTop (1));
778 auto textColour
= (textColourToUse
== nullptr ? findColour (PopupMenu::textColourId
)
781 auto r
= area
.reduced (1);
783 if (isHighlighted
&& isActive
)
785 g
.setColour (findColour (PopupMenu::highlightedBackgroundColourId
));
788 g
.setColour (findColour (PopupMenu::highlightedTextColourId
));
792 g
.setColour (textColour
.withMultipliedAlpha (isActive
? 1.0f
: 0.5f
));
795 r
.reduce (jmin (5, area
.getWidth() / 20), 0);
797 auto font
= getPopupMenuFont();
799 auto maxFontHeight
= (float) r
.getHeight() / 1.3f
;
801 if (font
.getHeight() > maxFontHeight
)
802 font
.setHeight (maxFontHeight
);
806 auto iconArea
= r
.removeFromLeft (roundToInt (maxFontHeight
)).toFloat();
810 icon
->drawWithin (g
, iconArea
, RectanglePlacement::centred
| RectanglePlacement::onlyReduceInSize
, 1.0f
);
811 r
.removeFromLeft (roundToInt (maxFontHeight
* 0.5f
));
815 auto tick
= getTickShape (1.0f
);
816 g
.fillPath (tick
, tick
.getTransformToScaleToFit (iconArea
.reduced (iconArea
.getWidth() / 5, 0).toFloat(), true));
821 auto arrowH
= 0.6f
* getPopupMenuFont().getAscent();
823 auto x
= static_cast<float> (r
.removeFromRight ((int) arrowH
).getX());
824 auto halfH
= static_cast<float> (r
.getCentreY());
827 path
.startNewSubPath (x
, halfH
- arrowH
* 0.5f
);
828 path
.lineTo (x
+ arrowH
* 0.6f
, halfH
);
829 path
.lineTo (x
, halfH
+ arrowH
* 0.5f
);
831 g
.strokePath (path
, PathStrokeType (2.0f
));
834 r
.removeFromRight (3);
835 g
.drawFittedText (text
, r
, Justification::centredLeft
, 1);
837 if (shortcutKeyText
.isNotEmpty())
840 f2
.setHeight (f2
.getHeight() * 0.75f
);
841 f2
.setHorizontalScale (0.95f
);
844 g
.drawText (shortcutKeyText
, r
, Justification::centredRight
, true);
849 void LookAndFeel_V4::getIdealPopupMenuItemSize (const String
& text
, const bool isSeparator
,
850 int standardMenuItemHeight
, int& idealWidth
, int& idealHeight
)
855 idealHeight
= standardMenuItemHeight
> 0 ? standardMenuItemHeight
/ 10 : 10;
859 auto font
= getPopupMenuFont();
861 if (standardMenuItemHeight
> 0 && font
.getHeight() > (float) standardMenuItemHeight
/ 1.3f
)
862 font
.setHeight ((float) standardMenuItemHeight
/ 1.3f
);
864 idealHeight
= standardMenuItemHeight
> 0 ? standardMenuItemHeight
: roundToInt (font
.getHeight() * 1.3f
);
865 idealWidth
= font
.getStringWidth (text
) + idealHeight
* 2;
869 void LookAndFeel_V4::drawMenuBarBackground (Graphics
& g
, int width
, int height
,
870 bool, MenuBarComponent
& menuBar
)
872 auto colour
= menuBar
.findColour (TextButton::buttonColourId
).withAlpha (0.4f
);
874 Rectangle
<int> r (width
, height
);
876 g
.setColour (colour
.contrasting (0.15f
));
877 g
.fillRect (r
.removeFromTop (1));
878 g
.fillRect (r
.removeFromBottom (1));
880 g
.setGradientFill (ColourGradient::vertical (colour
, 0, colour
.darker (0.2f
), (float) height
));
884 void LookAndFeel_V4::drawMenuBarItem (Graphics
& g
, int width
, int height
,
885 int itemIndex
, const String
& itemText
,
886 bool isMouseOverItem
, bool isMenuOpen
,
887 bool /*isMouseOverBar*/, MenuBarComponent
& menuBar
)
889 if (! menuBar
.isEnabled())
891 g
.setColour (menuBar
.findColour (TextButton::textColourOffId
)
892 .withMultipliedAlpha (0.5f
));
894 else if (isMenuOpen
|| isMouseOverItem
)
896 g
.fillAll (menuBar
.findColour (TextButton::buttonOnColourId
));
897 g
.setColour (menuBar
.findColour (TextButton::textColourOnId
));
901 g
.setColour (menuBar
.findColour (TextButton::textColourOffId
));
904 g
.setFont (getMenuBarFont (menuBar
, itemIndex
, itemText
));
905 g
.drawFittedText (itemText
, 0, 0, width
, height
, Justification::centred
, 1);
908 //==============================================================================
909 void LookAndFeel_V4::drawComboBox (Graphics
& g
, int width
, int height
, bool,
910 int, int, int, int, ComboBox
& box
)
912 auto cornerSize
= box
.findParentComponentOfClass
<ChoicePropertyComponent
>() != nullptr ? 0.0f
: 3.0f
;
913 Rectangle
<int> boxBounds (0, 0, width
, height
);
915 g
.setColour (box
.findColour (ComboBox::backgroundColourId
));
916 g
.fillRoundedRectangle (boxBounds
.toFloat(), cornerSize
);
918 g
.setColour (box
.findColour (ComboBox::outlineColourId
));
919 g
.drawRoundedRectangle (boxBounds
.toFloat().reduced (0.5f
, 0.5f
), cornerSize
, 1.0f
);
921 Rectangle
<int> arrowZone (width
- 30, 0, 20, height
);
923 path
.startNewSubPath ((float) arrowZone
.getX() + 3.0f
, (float) arrowZone
.getCentreY() - 2.0f
);
924 path
.lineTo ((float) arrowZone
.getCentreX(), (float) arrowZone
.getCentreY() + 3.0f
);
925 path
.lineTo ((float) arrowZone
.getRight() - 3.0f
, (float) arrowZone
.getCentreY() - 2.0f
);
927 g
.setColour (box
.findColour (ComboBox::arrowColourId
).withAlpha ((box
.isEnabled() ? 0.9f
: 0.2f
)));
928 g
.strokePath (path
, PathStrokeType (2.0f
));
931 Font
LookAndFeel_V4::getComboBoxFont (ComboBox
& box
)
933 return { jmin (16.0f
, (float) box
.getHeight() * 0.85f
) };
936 void LookAndFeel_V4::positionComboBoxText (ComboBox
& box
, Label
& label
)
938 label
.setBounds (1, 1,
940 box
.getHeight() - 2);
942 label
.setFont (getComboBoxFont (box
));
945 //==============================================================================
946 int LookAndFeel_V4::getSliderThumbRadius (Slider
& slider
)
948 return jmin (12, slider
.isHorizontal() ? static_cast<int> ((float) slider
.getHeight() * 0.5f
)
949 : static_cast<int> ((float) slider
.getWidth() * 0.5f
));
952 void LookAndFeel_V4::drawLinearSlider (Graphics
& g
, int x
, int y
, int width
, int height
,
956 const Slider::SliderStyle style
, Slider
& slider
)
960 g
.setColour (slider
.findColour (Slider::trackColourId
));
961 g
.fillRect (slider
.isHorizontal() ? Rectangle
<float> (static_cast<float> (x
), (float) y
+ 0.5f
, sliderPos
- (float) x
, (float) height
- 1.0f
)
962 : Rectangle
<float> ((float) x
+ 0.5f
, sliderPos
, (float) width
- 1.0f
, (float) y
+ ((float) height
- sliderPos
)));
966 auto isTwoVal
= (style
== Slider::SliderStyle::TwoValueVertical
|| style
== Slider::SliderStyle::TwoValueHorizontal
);
967 auto isThreeVal
= (style
== Slider::SliderStyle::ThreeValueVertical
|| style
== Slider::SliderStyle::ThreeValueHorizontal
);
969 auto trackWidth
= jmin (6.0f
, slider
.isHorizontal() ? (float) height
* 0.25f
: (float) width
* 0.25f
);
971 Point
<float> startPoint (slider
.isHorizontal() ? (float) x
: (float) x
+ (float) width
* 0.5f
,
972 slider
.isHorizontal() ? (float) y
+ (float) height
* 0.5f
: (float) (height
+ y
));
974 Point
<float> endPoint (slider
.isHorizontal() ? (float) (width
+ x
) : startPoint
.x
,
975 slider
.isHorizontal() ? startPoint
.y
: (float) y
);
977 Path backgroundTrack
;
978 backgroundTrack
.startNewSubPath (startPoint
);
979 backgroundTrack
.lineTo (endPoint
);
980 g
.setColour (slider
.findColour (Slider::backgroundColourId
));
981 g
.strokePath (backgroundTrack
, { trackWidth
, PathStrokeType::curved
, PathStrokeType::rounded
});
984 Point
<float> minPoint
, maxPoint
, thumbPoint
;
986 if (isTwoVal
|| isThreeVal
)
988 minPoint
= { slider
.isHorizontal() ? minSliderPos
: (float) width
* 0.5f
,
989 slider
.isHorizontal() ? (float) height
* 0.5f
: minSliderPos
};
992 thumbPoint
= { slider
.isHorizontal() ? sliderPos
: (float) width
* 0.5f
,
993 slider
.isHorizontal() ? (float) height
* 0.5f
: sliderPos
};
995 maxPoint
= { slider
.isHorizontal() ? maxSliderPos
: (float) width
* 0.5f
,
996 slider
.isHorizontal() ? (float) height
* 0.5f
: maxSliderPos
};
1000 auto kx
= slider
.isHorizontal() ? sliderPos
: ((float) x
+ (float) width
* 0.5f
);
1001 auto ky
= slider
.isHorizontal() ? ((float) y
+ (float) height
* 0.5f
) : sliderPos
;
1003 minPoint
= startPoint
;
1004 maxPoint
= { kx
, ky
};
1007 auto thumbWidth
= getSliderThumbRadius (slider
);
1009 valueTrack
.startNewSubPath (minPoint
);
1010 valueTrack
.lineTo (isThreeVal
? thumbPoint
: maxPoint
);
1011 g
.setColour (slider
.findColour (Slider::trackColourId
));
1012 g
.strokePath (valueTrack
, { trackWidth
, PathStrokeType::curved
, PathStrokeType::rounded
});
1016 g
.setColour (slider
.findColour (Slider::thumbColourId
));
1017 g
.fillEllipse (Rectangle
<float> (static_cast<float> (thumbWidth
), static_cast<float> (thumbWidth
)).withCentre (isThreeVal
? thumbPoint
: maxPoint
));
1020 if (isTwoVal
|| isThreeVal
)
1022 auto sr
= jmin (trackWidth
, (slider
.isHorizontal() ? (float) height
: (float) width
) * 0.4f
);
1023 auto pointerColour
= slider
.findColour (Slider::thumbColourId
);
1025 if (slider
.isHorizontal())
1027 drawPointer (g
, minSliderPos
- sr
,
1028 jmax (0.0f
, (float) y
+ (float) height
* 0.5f
- trackWidth
* 2.0f
),
1029 trackWidth
* 2.0f
, pointerColour
, 2);
1031 drawPointer (g
, maxSliderPos
- trackWidth
,
1032 jmin ((float) (y
+ height
) - trackWidth
* 2.0f
, (float) y
+ (float) height
* 0.5f
),
1033 trackWidth
* 2.0f
, pointerColour
, 4);
1037 drawPointer (g
, jmax (0.0f
, (float) x
+ (float) width
* 0.5f
- trackWidth
* 2.0f
),
1038 minSliderPos
- trackWidth
,
1039 trackWidth
* 2.0f
, pointerColour
, 1);
1041 drawPointer (g
, jmin ((float) (x
+ width
) - trackWidth
* 2.0f
, (float) x
+ (float) width
* 0.5f
), maxSliderPos
- sr
,
1042 trackWidth
* 2.0f
, pointerColour
, 3);
1048 void LookAndFeel_V4::drawRotarySlider (Graphics
& g
, int x
, int y
, int width
, int height
, float sliderPos
,
1049 const float rotaryStartAngle
, const float rotaryEndAngle
, Slider
& slider
)
1051 auto outline
= slider
.findColour (Slider::rotarySliderOutlineColourId
);
1052 auto fill
= slider
.findColour (Slider::rotarySliderFillColourId
);
1054 auto bounds
= Rectangle
<int> (x
, y
, width
, height
).toFloat().reduced (10);
1056 auto radius
= jmin (bounds
.getWidth(), bounds
.getHeight()) / 2.0f
;
1057 auto toAngle
= rotaryStartAngle
+ sliderPos
* (rotaryEndAngle
- rotaryStartAngle
);
1058 auto lineW
= jmin (8.0f
, radius
* 0.5f
);
1059 auto arcRadius
= radius
- lineW
* 0.5f
;
1062 backgroundArc
.addCentredArc (bounds
.getCentreX(),
1063 bounds
.getCentreY(),
1071 g
.setColour (outline
);
1072 g
.strokePath (backgroundArc
, PathStrokeType (lineW
, PathStrokeType::curved
, PathStrokeType::rounded
));
1074 if (slider
.isEnabled())
1077 valueArc
.addCentredArc (bounds
.getCentreX(),
1078 bounds
.getCentreY(),
1087 g
.strokePath (valueArc
, PathStrokeType (lineW
, PathStrokeType::curved
, PathStrokeType::rounded
));
1090 auto thumbWidth
= lineW
* 2.0f
;
1091 Point
<float> thumbPoint (bounds
.getCentreX() + arcRadius
* std::cos (toAngle
- MathConstants
<float>::halfPi
),
1092 bounds
.getCentreY() + arcRadius
* std::sin (toAngle
- MathConstants
<float>::halfPi
));
1094 g
.setColour (slider
.findColour (Slider::thumbColourId
));
1095 g
.fillEllipse (Rectangle
<float> (thumbWidth
, thumbWidth
).withCentre (thumbPoint
));
1098 void LookAndFeel_V4::drawPointer (Graphics
& g
, const float x
, const float y
, const float diameter
,
1099 const Colour
& colour
, const int direction
) noexcept
1102 p
.startNewSubPath (x
+ diameter
* 0.5f
, y
);
1103 p
.lineTo (x
+ diameter
, y
+ diameter
* 0.6f
);
1104 p
.lineTo (x
+ diameter
, y
+ diameter
);
1105 p
.lineTo (x
, y
+ diameter
);
1106 p
.lineTo (x
, y
+ diameter
* 0.6f
);
1109 p
.applyTransform (AffineTransform::rotation ((float) direction
* MathConstants
<float>::halfPi
,
1110 x
+ diameter
* 0.5f
, y
+ diameter
* 0.5f
));
1111 g
.setColour (colour
);
1115 Label
* LookAndFeel_V4::createSliderTextBox (Slider
& slider
)
1117 auto* l
= LookAndFeel_V2::createSliderTextBox (slider
);
1119 if (getCurrentColourScheme() == LookAndFeel_V4::getGreyColourScheme() && (slider
.getSliderStyle() == Slider::LinearBar
1120 || slider
.getSliderStyle() == Slider::LinearBarVertical
))
1122 l
->setColour (Label::textColourId
, Colours::black
.withAlpha (0.7f
));
1128 //==============================================================================
1129 void LookAndFeel_V4::drawTooltip (Graphics
& g
, const String
& text
, int width
, int height
)
1131 Rectangle
<int> bounds (width
, height
);
1132 auto cornerSize
= 5.0f
;
1134 g
.setColour (findColour (TooltipWindow::backgroundColourId
));
1135 g
.fillRoundedRectangle (bounds
.toFloat(), cornerSize
);
1137 g
.setColour (findColour (TooltipWindow::outlineColourId
));
1138 g
.drawRoundedRectangle (bounds
.toFloat().reduced (0.5f
, 0.5f
), cornerSize
, 1.0f
);
1140 LookAndFeelHelpers::layoutTooltipText (text
, findColour (TooltipWindow::textColourId
))
1141 .draw (g
, { static_cast<float> (width
), static_cast<float> (height
) });
1144 //==============================================================================
1145 void LookAndFeel_V4::drawConcertinaPanelHeader (Graphics
& g
, const Rectangle
<int>& area
,
1146 bool isMouseOver
, bool /*isMouseDown*/,
1147 ConcertinaPanel
& concertina
, Component
& panel
)
1149 auto bounds
= area
.toFloat().reduced (0.5f
);
1150 auto cornerSize
= 4.0f
;
1151 auto isTopPanel
= (concertina
.getPanel (0) == &panel
);
1154 p
.addRoundedRectangle (bounds
.getX(), bounds
.getY(), bounds
.getWidth(), bounds
.getHeight(),
1155 cornerSize
, cornerSize
, isTopPanel
, isTopPanel
, false, false);
1157 g
.setGradientFill (ColourGradient::vertical (Colours::white
.withAlpha (isMouseOver
? 0.4f
: 0.2f
), static_cast<float> (area
.getY()),
1158 Colours::darkgrey
.withAlpha (0.1f
), static_cast<float> (area
.getBottom())));
1162 //==============================================================================
1163 void LookAndFeel_V4::drawLevelMeter (Graphics
& g
, int width
, int height
, float level
)
1165 auto outerCornerSize
= 3.0f
;
1166 auto outerBorderWidth
= 2.0f
;
1167 auto totalBlocks
= 7;
1168 auto spacingFraction
= 0.03f
;
1170 g
.setColour (findColour (ResizableWindow::backgroundColourId
));
1171 g
.fillRoundedRectangle (0.0f
, 0.0f
, static_cast<float> (width
), static_cast<float> (height
), outerCornerSize
);
1173 auto doubleOuterBorderWidth
= 2.0f
* outerBorderWidth
;
1174 auto numBlocks
= roundToInt ((float) totalBlocks
* level
);
1176 auto blockWidth
= ((float) width
- doubleOuterBorderWidth
) / static_cast<float> (totalBlocks
);
1177 auto blockHeight
= (float) height
- doubleOuterBorderWidth
;
1179 auto blockRectWidth
= (1.0f
- 2.0f
* spacingFraction
) * blockWidth
;
1180 auto blockRectSpacing
= spacingFraction
* blockWidth
;
1182 auto blockCornerSize
= 0.1f
* blockWidth
;
1184 auto c
= findColour (Slider::thumbColourId
);
1186 for (auto i
= 0; i
< totalBlocks
; ++i
)
1189 g
.setColour (c
.withAlpha (0.5f
));
1191 g
.setColour (i
< totalBlocks
- 1 ? c
: Colours::red
);
1193 g
.fillRoundedRectangle (outerBorderWidth
+ ((float) i
* blockWidth
) + blockRectSpacing
,
1201 //==============================================================================
1202 void LookAndFeel_V4::paintToolbarBackground (Graphics
& g
, int w
, int h
, Toolbar
& toolbar
)
1204 auto background
= toolbar
.findColour (Toolbar::backgroundColourId
);
1206 g
.setGradientFill ({ background
, 0.0f
, 0.0f
,
1207 background
.darker (0.2f
),
1208 toolbar
.isVertical() ? (float) w
- 1.0f
: 0.0f
,
1209 toolbar
.isVertical() ? 0.0f
: (float) h
- 1.0f
,
1214 void LookAndFeel_V4::paintToolbarButtonLabel (Graphics
& g
, int x
, int y
, int width
, int height
,
1215 const String
& text
, ToolbarItemComponent
& component
)
1217 auto baseTextColour
= component
.findParentComponentOfClass
<PopupMenu::CustomComponent
>() != nullptr
1218 ? component
.findColour (PopupMenu::textColourId
)
1219 : component
.findColour (Toolbar::labelTextColourId
);
1221 g
.setColour (baseTextColour
.withAlpha (component
.isEnabled() ? 1.0f
: 0.25f
));
1223 auto fontHeight
= jmin (14.0f
, (float) height
* 0.85f
);
1224 g
.setFont (fontHeight
);
1226 g
.drawFittedText (text
,
1227 x
, y
, width
, height
,
1228 Justification::centred
,
1229 jmax (1, height
/ (int) fontHeight
));
1232 //==============================================================================
1233 void LookAndFeel_V4::drawPropertyPanelSectionHeader (Graphics
& g
, const String
& name
,
1234 bool isOpen
, int width
, int height
)
1236 auto buttonSize
= (float) height
* 0.75f
;
1237 auto buttonIndent
= ((float) height
- buttonSize
) * 0.5f
;
1239 drawTreeviewPlusMinusBox (g
, { buttonIndent
, buttonIndent
, buttonSize
, buttonSize
},
1240 findColour (ResizableWindow::backgroundColourId
), isOpen
, false);
1242 auto textX
= static_cast<int> ((buttonIndent
* 2.0f
+ buttonSize
+ 2.0f
));
1244 g
.setColour (findColour (PropertyComponent::labelTextColourId
));
1246 g
.setFont ({ (float) height
* 0.7f
, Font::bold
});
1247 g
.drawText (name
, textX
, 0, width
- textX
- 4, height
, Justification::centredLeft
, true);
1250 void LookAndFeel_V4::drawPropertyComponentBackground (Graphics
& g
, int width
, int height
, PropertyComponent
& component
)
1252 g
.setColour (component
.findColour (PropertyComponent::backgroundColourId
));
1253 g
.fillRect (0, 0, width
, height
- 1);
1256 void LookAndFeel_V4::drawPropertyComponentLabel (Graphics
& g
, int width
, int height
, PropertyComponent
& component
)
1258 ignoreUnused (width
);
1260 auto indent
= getPropertyComponentIndent (component
);
1262 g
.setColour (component
.findColour (PropertyComponent::labelTextColourId
)
1263 .withMultipliedAlpha (component
.isEnabled() ? 1.0f
: 0.6f
));
1265 g
.setFont ((float) jmin (height
, 24) * 0.65f
);
1267 auto r
= getPropertyComponentContentPosition (component
);
1269 g
.drawFittedText (component
.getName(),
1270 indent
, r
.getY(), r
.getX() - 5, r
.getHeight(),
1271 Justification::centredLeft
, 2);
1274 int LookAndFeel_V4::getPropertyComponentIndent (PropertyComponent
& component
)
1276 return jmin (10, component
.getWidth() / 10);
1279 Rectangle
<int> LookAndFeel_V4::getPropertyComponentContentPosition (PropertyComponent
& component
)
1281 auto textW
= jmin (200, component
.getWidth() / 2);
1282 return { textW
, 0, component
.getWidth() - textW
, component
.getHeight() - 1 };
1285 //==============================================================================
1286 void LookAndFeel_V4::drawCallOutBoxBackground (CallOutBox
& box
, Graphics
& g
,
1287 const Path
& path
, Image
& cachedImage
)
1289 if (cachedImage
.isNull())
1291 cachedImage
= { Image::ARGB
, box
.getWidth(), box
.getHeight(), true };
1292 Graphics
g2 (cachedImage
);
1294 DropShadow (Colours::black
.withAlpha (0.7f
), 8, { 0, 2 }).drawForPath (g2
, path
);
1297 g
.setColour (Colours::black
);
1298 g
.drawImageAt (cachedImage
, 0, 0);
1300 g
.setColour (currentColourScheme
.getUIColour (ColourScheme::UIColour::widgetBackground
).withAlpha (0.8f
));
1303 g
.setColour (currentColourScheme
.getUIColour (ColourScheme::UIColour::outline
).withAlpha (0.8f
));
1304 g
.strokePath (path
, PathStrokeType (2.0f
));
1307 //==============================================================================
1308 void LookAndFeel_V4::drawStretchableLayoutResizerBar (Graphics
& g
, int /*w*/, int /*h*/, bool /*isVerticalBar*/,
1309 bool isMouseOver
, bool isMouseDragging
)
1311 if (isMouseOver
|| isMouseDragging
)
1312 g
.fillAll (currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultFill
).withAlpha (0.5f
));
1315 //==============================================================================
1316 void LookAndFeel_V4::initialiseColours()
1318 const uint32 transparent
= 0x00000000;
1320 const uint32 coloursToUse
[] =
1322 TextButton::buttonColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::widgetBackground
).getARGB(),
1323 TextButton::buttonOnColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::highlightedFill
).getARGB(),
1324 TextButton::textColourOnId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::highlightedText
).getARGB(),
1325 TextButton::textColourOffId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultText
).getARGB(),
1327 ToggleButton::textColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultText
).getARGB(),
1328 ToggleButton::tickColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultText
).getARGB(),
1329 ToggleButton::tickDisabledColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultText
).withAlpha (0.5f
).getARGB(),
1331 TextEditor::backgroundColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::widgetBackground
).getARGB(),
1332 TextEditor::textColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultText
).getARGB(),
1333 TextEditor::highlightColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultFill
).withAlpha (0.4f
).getARGB(),
1334 TextEditor::highlightedTextColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::highlightedText
).getARGB(),
1335 TextEditor::outlineColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::outline
).getARGB(),
1336 TextEditor::focusedOutlineColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::outline
).getARGB(),
1337 TextEditor::shadowColourId
, transparent
,
1339 CaretComponent::caretColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultFill
).getARGB(),
1341 Label::backgroundColourId
, transparent
,
1342 Label::textColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultText
).getARGB(),
1343 Label::outlineColourId
, transparent
,
1344 Label::textWhenEditingColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultText
).getARGB(),
1346 ScrollBar::backgroundColourId
, transparent
,
1347 ScrollBar::thumbColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultFill
).getARGB(),
1348 ScrollBar::trackColourId
, transparent
,
1350 TreeView::linesColourId
, transparent
,
1351 TreeView::backgroundColourId
, transparent
,
1352 TreeView::dragAndDropIndicatorColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::outline
).getARGB(),
1353 TreeView::selectedItemBackgroundColourId
, transparent
,
1354 TreeView::oddItemsColourId
, transparent
,
1355 TreeView::evenItemsColourId
, transparent
,
1357 PopupMenu::backgroundColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::menuBackground
).getARGB(),
1358 PopupMenu::textColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::menuText
).getARGB(),
1359 PopupMenu::headerTextColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::menuText
).getARGB(),
1360 PopupMenu::highlightedTextColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::highlightedText
).getARGB(),
1361 PopupMenu::highlightedBackgroundColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::highlightedFill
).getARGB(),
1363 ComboBox::buttonColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::outline
).getARGB(),
1364 ComboBox::outlineColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::outline
).getARGB(),
1365 ComboBox::textColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultText
).getARGB(),
1366 ComboBox::backgroundColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::widgetBackground
).getARGB(),
1367 ComboBox::arrowColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultText
).getARGB(),
1368 ComboBox::focusedOutlineColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::outline
).getARGB(),
1370 PropertyComponent::backgroundColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::widgetBackground
).getARGB(),
1371 PropertyComponent::labelTextColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultText
).getARGB(),
1373 TextPropertyComponent::backgroundColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::widgetBackground
).getARGB(),
1374 TextPropertyComponent::textColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultText
).getARGB(),
1375 TextPropertyComponent::outlineColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::outline
).getARGB(),
1377 BooleanPropertyComponent::backgroundColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::widgetBackground
).getARGB(),
1378 BooleanPropertyComponent::outlineColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::outline
).getARGB(),
1380 ListBox::backgroundColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::widgetBackground
).getARGB(),
1381 ListBox::outlineColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::outline
).getARGB(),
1382 ListBox::textColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultText
).getARGB(),
1384 Slider::backgroundColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::widgetBackground
).getARGB(),
1385 Slider::thumbColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultFill
).getARGB(),
1386 Slider::trackColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::highlightedFill
).getARGB(),
1387 Slider::rotarySliderFillColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::highlightedFill
).getARGB(),
1388 Slider::rotarySliderOutlineColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::widgetBackground
).getARGB(),
1389 Slider::textBoxTextColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultText
).getARGB(),
1390 Slider::textBoxBackgroundColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::widgetBackground
).withAlpha (0.0f
).getARGB(),
1391 Slider::textBoxHighlightColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultFill
).withAlpha (0.4f
).getARGB(),
1392 Slider::textBoxOutlineColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::outline
).getARGB(),
1394 ResizableWindow::backgroundColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::windowBackground
).getARGB(),
1396 DocumentWindow::textColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultText
).getARGB(),
1398 AlertWindow::backgroundColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::widgetBackground
).getARGB(),
1399 AlertWindow::textColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultText
).getARGB(),
1400 AlertWindow::outlineColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::outline
).getARGB(),
1402 ProgressBar::backgroundColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::widgetBackground
).getARGB(),
1403 ProgressBar::foregroundColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::highlightedFill
).getARGB(),
1405 TooltipWindow::backgroundColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::highlightedFill
).getARGB(),
1406 TooltipWindow::textColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::highlightedText
).getARGB(),
1407 TooltipWindow::outlineColourId
, transparent
,
1409 TabbedComponent::backgroundColourId
, transparent
,
1410 TabbedComponent::outlineColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::outline
).getARGB(),
1411 TabbedButtonBar::tabOutlineColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::outline
).withAlpha (0.5f
).getARGB(),
1412 TabbedButtonBar::frontOutlineColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::outline
).getARGB(),
1414 Toolbar::backgroundColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::widgetBackground
).withAlpha (0.4f
).getARGB(),
1415 Toolbar::separatorColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::outline
).getARGB(),
1416 Toolbar::buttonMouseOverBackgroundColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::widgetBackground
).contrasting (0.2f
).getARGB(),
1417 Toolbar::buttonMouseDownBackgroundColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::widgetBackground
).contrasting (0.5f
).getARGB(),
1418 Toolbar::labelTextColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultText
).getARGB(),
1419 Toolbar::editingModeOutlineColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::outline
).getARGB(),
1421 DrawableButton::textColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultText
).getARGB(),
1422 DrawableButton::textColourOnId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::highlightedText
).getARGB(),
1423 DrawableButton::backgroundColourId
, transparent
,
1424 DrawableButton::backgroundOnColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::highlightedFill
).getARGB(),
1426 HyperlinkButton::textColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultText
).interpolatedWith (Colours::blue
, 0.4f
).getARGB(),
1428 GroupComponent::outlineColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::outline
).getARGB(),
1429 GroupComponent::textColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultText
).getARGB(),
1431 BubbleComponent::backgroundColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::widgetBackground
).getARGB(),
1432 BubbleComponent::outlineColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::outline
).getARGB(),
1434 DirectoryContentsDisplayComponent::highlightColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::highlightedFill
).getARGB(),
1435 DirectoryContentsDisplayComponent::textColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::menuText
).getARGB(),
1436 DirectoryContentsDisplayComponent::highlightedTextColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::highlightedText
).getARGB(),
1438 0x1000440, /*LassoComponent::lassoFillColourId*/ currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultFill
).getARGB(),
1439 0x1000441, /*LassoComponent::lassoOutlineColourId*/ currentColourScheme
.getUIColour (ColourScheme::UIColour::outline
).getARGB(),
1441 0x1004000, /*KeyboardComponentBase::upDownButtonBackgroundColourId*/ 0xffd3d3d3,
1442 0x1004001, /*KeyboardComponentBase::upDownButtonArrowColourId*/ 0xff000000,
1444 0x1005000, /*MidiKeyboardComponent::whiteNoteColourId*/ 0xffffffff,
1445 0x1005001, /*MidiKeyboardComponent::blackNoteColourId*/ 0xff000000,
1446 0x1005002, /*MidiKeyboardComponent::keySeparatorLineColourId*/ 0x66000000,
1447 0x1005003, /*MidiKeyboardComponent::mouseOverKeyOverlayColourId*/ 0x80ffff00,
1448 0x1005004, /*MidiKeyboardComponent::keyDownOverlayColourId*/ 0xffb6b600,
1449 0x1005005, /*MidiKeyboardComponent::textLabelColourId*/ 0xff000000,
1450 0x1005006, /*MidiKeyboardComponent::shadowColourId*/ 0x4c000000,
1452 0x1006000, /*MPEKeyboardComponent::whiteNoteColourId*/ 0xff1a1c27,
1453 0x1006001, /*MPEKeyboardComponent::blackNoteColourId*/ 0x99f1f1f1,
1454 0x1006002, /*MPEKeyboardComponent::textLabelColourId*/ 0xfff1f1f1,
1455 0x1006003, /*MPEKeyboardComponent::noteCircleFillColourId*/ 0x99ba00ff,
1456 0x1006004, /*MPEKeyboardComponent::noteCircleOutlineColourId*/ 0xfff1f1f1,
1458 0x1004500, /*CodeEditorComponent::backgroundColourId*/ currentColourScheme
.getUIColour (ColourScheme::UIColour::widgetBackground
).getARGB(),
1459 0x1004502, /*CodeEditorComponent::highlightColourId*/ currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultFill
).withAlpha (0.4f
).getARGB(),
1460 0x1004503, /*CodeEditorComponent::defaultTextColourId*/ currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultText
).getARGB(),
1461 0x1004504, /*CodeEditorComponent::lineNumberBackgroundId*/ currentColourScheme
.getUIColour (ColourScheme::UIColour::highlightedFill
).withAlpha (0.5f
).getARGB(),
1462 0x1004505, /*CodeEditorComponent::lineNumberTextId*/ currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultFill
).getARGB(),
1464 0x1007000, /*ColourSelector::backgroundColourId*/ currentColourScheme
.getUIColour (ColourScheme::UIColour::widgetBackground
).getARGB(),
1465 0x1007001, /*ColourSelector::labelTextColourId*/ currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultText
).getARGB(),
1467 0x100ad00, /*KeyMappingEditorComponent::backgroundColourId*/ currentColourScheme
.getUIColour (ColourScheme::UIColour::widgetBackground
).getARGB(),
1468 0x100ad01, /*KeyMappingEditorComponent::textColourId*/ currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultText
).getARGB(),
1470 FileSearchPathListComponent::backgroundColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::menuBackground
).getARGB(),
1472 FileChooserDialogBox::titleTextColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultText
).getARGB(),
1474 SidePanel::backgroundColour
, currentColourScheme
.getUIColour (ColourScheme::UIColour::widgetBackground
).getARGB(),
1475 SidePanel::titleTextColour
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultText
).getARGB(),
1476 SidePanel::shadowBaseColour
, currentColourScheme
.getUIColour (ColourScheme::UIColour::widgetBackground
).darker().getARGB(),
1477 SidePanel::dismissButtonNormalColour
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultFill
).getARGB(),
1478 SidePanel::dismissButtonOverColour
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultFill
).darker().getARGB(),
1479 SidePanel::dismissButtonDownColour
, currentColourScheme
.getUIColour (ColourScheme::UIColour::defaultFill
).brighter().getARGB(),
1481 FileBrowserComponent::currentPathBoxBackgroundColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::menuBackground
).getARGB(),
1482 FileBrowserComponent::currentPathBoxTextColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::menuText
).getARGB(),
1483 FileBrowserComponent::currentPathBoxArrowColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::menuText
).getARGB(),
1484 FileBrowserComponent::filenameBoxBackgroundColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::menuBackground
).getARGB(),
1485 FileBrowserComponent::filenameBoxTextColourId
, currentColourScheme
.getUIColour (ColourScheme::UIColour::menuText
).getARGB(),
1488 for (int i
= 0; i
< numElementsInArray (coloursToUse
); i
+= 2)
1489 setColour ((int) coloursToUse
[i
], Colour ((uint32
) coloursToUse
[i
+ 1]));