paulxstretch/Source/CustomLookAndFeel.cpp

1315 lines
52 KiB
C++
Raw Normal View History

// SPDX-License-Identifier: GPLv3-or-later WITH Appstore-exception
// Copyright (C) 2020 Jesse Chappell
#include "CustomLookAndFeel.h"
//==============================================================================
CustomLookAndFeel::CustomLookAndFeel()
{
// setColour (mainBackgroundColourId, Colour::greyLevel (0.8f));
//DBG("Sonolook and feel");
setUsingNativeAlertWindows(true);
fontScale = 1.0;
setColourScheme(getDarkColourScheme());
getCurrentColourScheme().setUIColour(ColourScheme::UIColour::windowBackground, Colour::fromFloatRGBA(0.0, 0.0, 0.0, 1.0));
getCurrentColourScheme().setUIColour(ColourScheme::UIColour::widgetBackground, Colour::fromFloatRGBA(0.1, 0.1, 0.1, 1.0));
getCurrentColourScheme().setUIColour(ColourScheme::UIColour::outline, Colour::fromFloatRGBA(0.3, 0.3, 0.3, 0.5));
setColour (Label::textColourId, Colour (0xffcccccc));
setColour (Label::textWhenEditingColourId, Colour (0xffe9e9e9));
setColour(ResizableWindow::backgroundColourId, Colour(0xff111111));
//setColour (TextButton::buttonColourId, Colour (0xff363636));
setColour (TextButton::buttonColourId, Colour::fromFloatRGBA(0.15, 0.15, 0.15, 0.7)); // old one
//setColour (TextButton::buttonColourId, Colour::fromFloatRGBA(0.15, 0.15, 0.15, 0.0));
//setColour (TextButton::buttonOnColourId, Colour (0xff3d70c8));
setColour (TextButton::buttonOnColourId, Colour::fromFloatRGBA(0.5, 0.4, 0.6, 0.8));
setColour (TextButton::textColourOnId, Colour (0xddcccccc));
setColour (TextButton::textColourOffId, Colour (0xdde9e9e9));
setColour (ToggleButton::textColourId, Colour (0xddcccccc));
2022-04-13 23:24:44 +00:00
setColour (ScrollBar::ColourIds::thumbColourId, Colour::fromFloatRGBA(0.7, 0.7, 0.7, 0.7));
//setColour (ComboBox::backgroundColourId, Colour (0xff161616));
setColour (ComboBox::backgroundColourId, Colour::fromFloatRGBA(0.15, 0.15, 0.15, 0.7));
setColour (ComboBox::textColourId, Colour (0xffe9e9e9));
setColour (ComboBox::outlineColourId, Colour::fromFloatRGBA(0.3, 0.3, 0.3, 0.5));
setColour (TextEditor::backgroundColourId, Colour (0xff050505));
setColour (TextEditor::textColourId, Colour (0xffe9e9e9));
setColour (TextEditor::highlightColourId, Colour (0xff5959f9));
setColour (TextEditor::outlineColourId, Colour::fromFloatRGBA(0.3, 0.3, 0.3, 0.5));
setColour (TextEditor::focusedOutlineColourId, Colour::fromFloatRGBA(0.5, 0.5, 0.5, 0.7));
setColour (Slider::backgroundColourId, Colour::fromFloatRGBA(0.2, 0.2, 0.2, 1.0));
setColour (Slider::rotarySliderOutlineColourId, Colour::fromFloatRGBA(0.2, 0.2, 0.2, 1.0));
setColour (Slider::textBoxTextColourId, Colour(0xddcccccc));
setColour (Slider::textBoxBackgroundColourId, Colour::fromFloatRGBA(0.05, 0.05, 0.05, 1.0));
setColour (Slider::textBoxHighlightColourId, Colour (0xaa555555));
setColour (Slider::textBoxOutlineColourId, Colour::fromFloatRGBA(0.3, 0.3, 0.3, 0.5));
setColour (Slider::trackColourId, Colour::fromFloatRGBA(0.1, 0.4, 0.6, 0.8));
setColour (Slider::thumbColourId, Colour::fromFloatRGBA(0.5, 0.4, 0.6, 0.9));
//setColour (Slider::thumbColourId, Colour::fromFloatRGBA(0.2, 0.5, 0.7, 1.0));
setColour (Slider::rotarySliderFillColourId, Colour::fromFloatRGBA(0.5, 0.4, 0.6, 0.9));
2022-04-13 23:24:44 +00:00
setColour (TabbedButtonBar::tabOutlineColourId, Colour::fromFloatRGBA(0.3, 0.3, 0.3, 0.6));
setColour (TabbedComponent::outlineColourId, Colour::fromFloatRGBA(0.2, 0.2, 0.2, 0.5));
setColour (ListBox::backgroundColourId, Colour::fromFloatRGBA(0.15, 0.15, 0.15, 0.7));
setColour (ListBox::outlineColourId, Colour::fromFloatRGBA(0.3, 0.3, 0.3, 0.5));
setColour (BubbleComponent::backgroundColourId, Colour::fromFloatRGBA(0.25, 0.25, 0.25, 1.0));
setColour (BubbleComponent::outlineColourId, Colour::fromFloatRGBA(0.4, 0.4, 0.4, 0.5));
//setColour (TooltipWindow::textColourId, Colour(0xeecccccc));
setColour (TooltipWindow::textColourId, Colour(0xee222222));
setColour (TooltipWindow::backgroundColourId, Colour(0xeeffff99));
setColour (PopupMenu::backgroundColourId, Colour::fromFloatRGBA(0.2, 0.2, 0.2, 1.0));
setColour (PopupMenu::highlightedBackgroundColourId, Colour::fromFloatRGBA(0.35, 0.35, 0.4, 1.0));
setColour (SidePanel::backgroundColour, Colour::fromFloatRGBA(0.17, 0.17, 0.17, 1.0));
//setColour (SonoDrawableButton::overOverlayColourId, Colour::fromFloatRGBA(0.8, 0.8, 0.8, 0.08));
//setColour (SonoDrawableButton::downOverlayColourId, Colour::fromFloatRGBA(0.8, 0.8, 0.8, 0.3));
setColour (DrawableButton::textColourId, Colour (0xffb9b9b9));
setColour (DrawableButton::textColourOnId, Colour (0xffe9e9e9));
//setColour (DrawableButton::backgroundColourId, Colour (0xffb9b9b9));
setColour (DrawableButton::backgroundOnColourId, Colour::fromFloatRGBA(0.5, 0.4, 0.6, 0.8));
//setColour (ConfigurationRowView::backgroundColourId, Colour::fromFloatRGBA(0.05, 0.05, 0.05, 1.0));
//setColour (ConfigurationRowView::selectedBackgroundColourId, Colour::fromFloatRGBA(0.15, 0.15, 0.15, 1.0));
setColour(ToggleButton::tickColourId, Colour::fromFloatRGBA(0.4, 0.8, 1.0, 1.0));
setColour (DirectoryContentsDisplayComponent::highlightColourId, Colour::fromFloatRGBA(0.1, 0.4, 0.6, 0.9));
setColour (DirectoryContentsDisplayComponent::textColourId, Colour (0xffe9e9e9));
// setColour (Label::textColourId, Colour (0xffe9e9e9));
//myFont = Typeface::createSystemTypefaceFor (BinaryData::DejaVuSans_ttf, BinaryData::DejaVuSans_ttfSize);
//setDefaultSansSerifTypefaceName("Gill Sans");
//setDefaultSansSerifTypefaceName("Arial Unicode MS");
//setDefaultSansSerifTypefaceName(myFont.getTypefaceName());
//myFont = Typeface::createSystemTypefaceFor (BinaryData::GillSans_ttc, BinaryData::GillSans_ttcSize);
myFont = Font(16 * fontScale);
if (auto * deflnf = dynamic_cast<CustomLookAndFeel*>(&LookAndFeel::getDefaultLookAndFeel())) {
setLanguageCode(deflnf->languageCode);
}
//DBG("Myfont name " << myFont.getTypefaceName());
}
void CustomLookAndFeel::setLanguageCode(const String & lang)
{
languageCode = lang;
if (lang.startsWith("zh")) {
fontScale = 1.0f;
}
else if (lang.startsWith("ko")) {
fontScale = 1.15f;
}
}
Font CustomLookAndFeel::getMenuBarFont (MenuBarComponent& menuBar, int /*itemIndex*/, const String& /*itemText*/)
{
return Font (menuBar.getHeight() * 0.7f);
}
//==============================================================================
void CustomLookAndFeel::drawCallOutBoxBackground (CallOutBox& box, Graphics& g,
const Path& path, Image& cachedImage)
{
if (cachedImage.isNull())
{
cachedImage = Image (Image::ARGB, box.getWidth(), box.getHeight(), true);
Graphics g2 (cachedImage);
DropShadow (Colours::black.withAlpha (0.7f), 8, Point<int> (0, 2)).drawForPath (g2, path);
}
g.setColour (Colours::black);
g.drawImageAt (cachedImage, 0, 0);
//g.setColour (getCurrentColourScheme().getUIColour (ColourScheme::UIColour::widgetBackground).withAlpha (0.8f));
g.setColour (getCurrentColourScheme().getUIColour (ColourScheme::UIColour::widgetBackground));
g.fillPath (path);
g.setColour (getCurrentColourScheme().getUIColour (ColourScheme::UIColour::outline).withAlpha (0.8f));
g.strokePath (path, PathStrokeType (1.0f));
}
int CustomLookAndFeel::getTabButtonBestWidth (TabBarButton& button, int depth)
{
return 250; // 120;
}
int CustomLookAndFeel::getTabButtonSpaceAroundImage() {
return 0;
}
static Colour getTabBackgroundColour (TabBarButton& button)
{
const Colour bkg (button.findColour (TabbedComponent::backgroundColourId).contrasting (0.15f));
if (button.isFrontTab())
return bkg.overlaidWith (Colours::yellow.withAlpha (0.8f));
return bkg;
}
Rectangle<int> CustomLookAndFeel::getTabButtonExtraComponentBounds (const TabBarButton& button, Rectangle<int>& textArea, Component& comp)
{
Rectangle<int> extraComp;
auto orientation = button.getTabbedButtonBar().getOrientation();
if (button.getExtraComponentPlacement() == TabBarButton::beforeText)
{
switch (orientation)
{
case TabbedButtonBar::TabsAtBottom:
case TabbedButtonBar::TabsAtTop: extraComp = textArea.removeFromLeft (comp.getWidth()); break;
case TabbedButtonBar::TabsAtLeft: extraComp = textArea.removeFromBottom (comp.getHeight()); break;
case TabbedButtonBar::TabsAtRight: extraComp = textArea.removeFromTop (comp.getHeight()); break;
default: jassertfalse; break;
}
}
else if (button.getExtraComponentPlacement() == TabBarButton::afterText)
{
switch (orientation)
{
case TabbedButtonBar::TabsAtBottom:
case TabbedButtonBar::TabsAtTop: extraComp = textArea.removeFromRight (comp.getWidth()); break;
case TabbedButtonBar::TabsAtLeft: extraComp = textArea.removeFromTop (comp.getHeight()); break;
case TabbedButtonBar::TabsAtRight: extraComp = textArea.removeFromBottom (comp.getHeight()); break;
default: jassertfalse; break;
}
}
else if (button.getExtraComponentPlacement() == TabBarButton::aboveText)
{
switch (orientation)
{
case TabbedButtonBar::TabsAtBottom:
case TabbedButtonBar::TabsAtTop: extraComp = textArea.removeFromTop (comp.getHeight()); break;
case TabbedButtonBar::TabsAtLeft: extraComp = textArea.removeFromTop (comp.getHeight()); break;
case TabbedButtonBar::TabsAtRight: extraComp = textArea.removeFromTop (comp.getHeight()); break;
default: jassertfalse; break;
}
// DBG("Extra comp bounds: " << extraComp.toString())
extraComp.translate(0, 3);
//DBG("After Extra comp bounds: " << extraComp.toString())
}
else if (button.getExtraComponentPlacement() == TabBarButton::belowText)
{
switch (orientation)
{
case TabbedButtonBar::TabsAtBottom:
case TabbedButtonBar::TabsAtTop: extraComp = textArea.removeFromBottom (comp.getHeight()); break;
case TabbedButtonBar::TabsAtLeft: extraComp = textArea.removeFromBottom (comp.getHeight()); break;
case TabbedButtonBar::TabsAtRight: extraComp = textArea.removeFromBottom (comp.getHeight()); break;
default: jassertfalse; break;
}
}
return extraComp;
}
void CustomLookAndFeel::createTabTextLayout (const TabBarButton& button, float length, float depth,
Colour colour, TextLayout& textLayout)
{
float hscale = 0.6f;
#if JUCE_IOS
hscale = 0.5f;
#endif
float fontsize = button.getExtraComponent() != nullptr ? jmin(depth, 32.0f) * hscale : jmin(depth, 32.0f) * hscale;
Font font = myFont.withHeight(fontsize * fontScale);
font.setUnderline (button.hasKeyboardFocus (false));
AttributedString s;
s.setWordWrap(AttributedString::byWord);
s.setJustification (Justification::centred);
s.append (button.getButtonText().trim(), font, colour);
textLayout.createLayout (s, length);
}
void CustomLookAndFeel::drawTabButton (TabBarButton& button, Graphics& g, bool isMouseOver, bool isMouseDown)
{
const Rectangle<int> activeArea (button.getActiveArea());
const TabbedButtonBar::Orientation o = button.getTabbedButtonBar().getOrientation();
const Colour bkg (button.getTabBackgroundColour());
const Colour selcol = Colour::fromFloatRGBA(0.0f, 0.2f, 0.4f, 1.0f);
// DBG("Sono draw tab button");
if (button.getToggleState() && bkg != Colours::black)
{
//g.setColour (bkg);
g.setColour (selcol);
}
else
{
Point<int> p1, p2;
switch (o)
{
case TabbedButtonBar::TabsAtBottom: p1 = activeArea.getBottomLeft(); p2 = activeArea.getTopLeft(); break;
case TabbedButtonBar::TabsAtTop: p1 = activeArea.getTopLeft(); p2 = activeArea.getBottomLeft(); break;
case TabbedButtonBar::TabsAtRight: p1 = activeArea.getTopRight(); p2 = activeArea.getTopLeft(); break;
case TabbedButtonBar::TabsAtLeft: p1 = activeArea.getTopLeft(); p2 = activeArea.getTopRight(); break;
default: jassertfalse; break;
}
g.setColour(isMouseDown ? bkg.brighter(0.1) : bkg);
//g.setGradientFill (ColourGradient (bkg.darker (0.1f), (float) p1.x, (float) p1.y,
// bkg.darker (0.5f), (float) p2.x, (float) p2.y, false));
}
Rectangle<int> p (activeArea.reduced(1));
g.fillRect (p);
//g.fillRect (activeArea);
#if 0
g.setColour (button.findColour (TabbedButtonBar::tabOutlineColourId));
Rectangle<int> r (activeArea);
if (o != TabbedButtonBar::TabsAtBottom) g.fillRect (r.removeFromTop (1));
if (o != TabbedButtonBar::TabsAtTop) g.fillRect (r.removeFromBottom (1));
if (o != TabbedButtonBar::TabsAtRight) g.fillRect (r.removeFromLeft (1));
if (o != TabbedButtonBar::TabsAtLeft) g.fillRect (r.removeFromRight (1));
#endif
const float alpha = button.isEnabled() ? ((isMouseOver || isMouseDown) ? 1.0f : 0.8f) : 0.3f;
Colour col (bkg.contrasting().withMultipliedAlpha (alpha));
if (TabbedButtonBar* bar = button.findParentComponentOfClass<TabbedButtonBar>())
{
TabbedButtonBar::ColourIds colID = button.isFrontTab() ? TabbedButtonBar::frontTextColourId
: TabbedButtonBar::tabTextColourId;
if (bar->isColourSpecified (colID))
col = bar->findColour (colID);
else if (isColourSpecified (colID))
col = findColour (colID);
}
const Rectangle<float> area (button.getTextArea().toFloat());
float length = area.getWidth();
float depth = area.getHeight();
if (button.getTabbedButtonBar().isVertical())
std::swap (length, depth);
TextLayout textLayout;
createTabTextLayout (button, length, depth, col, textLayout);
AffineTransform t;
switch (o)
{
case TabbedButtonBar::TabsAtLeft: t = t.rotated (float_Pi * -0.5f).translated (area.getX(), area.getBottom()); break;
case TabbedButtonBar::TabsAtRight: t = t.rotated (float_Pi * 0.5f).translated (area.getRight(), area.getY()); break;
case TabbedButtonBar::TabsAtTop:
case TabbedButtonBar::TabsAtBottom: t = t.translated (area.getX(), area.getY()); break;
default: jassertfalse; break;
}
g.addTransform (t);
textLayout.draw (g, Rectangle<float> (length, depth));
}
/*
void CustomLookAndFeel::drawTabButton (TabBarButton& button, Graphics& g, bool isMouseOver, bool isMouseDown)
{
const Rectangle<int> activeArea (button.getActiveArea());
const Colour bkg (getTabBackgroundColour (button));
g.setGradientFill (ColourGradient (bkg.brighter (0.1f), 0, (float) activeArea.getY(),
bkg.darker (0.1f), 0, (float) activeArea.getBottom(), false));
g.fillRect (activeArea);
g.setColour (button.findColour (TabbedComponent::backgroundColourId).darker (0.3f));
g.drawRect (activeArea);
const float alpha = button.isEnabled() ? ((isMouseOver || isMouseDown) ? 1.0f : 0.8f) : 0.3f;
const Colour col (bkg.contrasting().withMultipliedAlpha (alpha));
TextLayout textLayout;
LookAndFeel_V3::createTabTextLayout (button, (float) activeArea.getWidth(), (float) activeArea.getHeight(), col, textLayout);
textLayout.draw (g, button.getTextArea().toFloat());
}
*/
void CustomLookAndFeel::drawTabbedButtonBarBackground (TabbedButtonBar&, Graphics&) {}
void CustomLookAndFeel::drawTabAreaBehindFrontButton (TabbedButtonBar& bar, Graphics& g, const int w, const int h)
{
const float shadowSize = 0.15f;
Rectangle<int> shadowRect, line;
ColourGradient gradient (Colours::black.withAlpha (bar.isEnabled() ? 0.08f : 0.04f), 0, 0,
Colours::transparentBlack, 0, 0, false);
switch (bar.getOrientation())
{
case TabbedButtonBar::TabsAtLeft:
gradient.point1.x = (float) w;
gradient.point2.x = w * (1.0f - shadowSize);
shadowRect.setBounds ((int) gradient.point2.x, 0, w - (int) gradient.point2.x, h);
line.setBounds (w - 1, 0, 1, h);
break;
case TabbedButtonBar::TabsAtRight:
gradient.point2.x = w * shadowSize;
shadowRect.setBounds (0, 0, (int) gradient.point2.x, h);
line.setBounds (0, 0, 1, h);
break;
case TabbedButtonBar::TabsAtTop:
gradient.point1.y = (float) h;
gradient.point2.y = h * (1.0f - shadowSize);
shadowRect.setBounds (0, (int) gradient.point2.y, w, h - (int) gradient.point2.y);
line.setBounds (0, h - 1, w, 1);
break;
case TabbedButtonBar::TabsAtBottom:
gradient.point2.y = h * shadowSize;
shadowRect.setBounds (0, 0, w, (int) gradient.point2.y);
line.setBounds (0, 0, w, 1);
break;
default: break;
}
g.setGradientFill (gradient);
g.fillRect (shadowRect.expanded (2, 2));
g.setColour (bar.findColour (TabbedButtonBar::tabOutlineColourId));
g.fillRect (line);
}
void CustomLookAndFeel::drawTabButtonText (TabBarButton& button, Graphics& g, bool isMouseOver, bool isMouseDown)
{
const Rectangle<float> area (button.getTextArea().toFloat());
//DBG("Sono look and feel drawtabbutton text: " << button.getButtonText());
float length = area.getWidth();
float depth = area.getHeight();
if (button.getTabbedButtonBar().isVertical())
std::swap (length, depth);
Font font = myFont.withHeight(jmin(depth,30.0f) * 0.6f * fontScale);
font.setUnderline (button.hasKeyboardFocus (false));
AffineTransform t;
switch (button.getTabbedButtonBar().getOrientation())
{
case TabbedButtonBar::TabsAtLeft: t = t.rotated (float_Pi * -0.5f).translated (area.getX(), area.getBottom()); break;
case TabbedButtonBar::TabsAtRight: t = t.rotated (float_Pi * 0.5f).translated (area.getRight(), area.getY()); break;
case TabbedButtonBar::TabsAtTop:
case TabbedButtonBar::TabsAtBottom: t = t.translated (area.getX(), area.getY()); break;
default: jassertfalse; break;
}
Colour col;
if (button.isFrontTab() && (button.isColourSpecified (TabbedButtonBar::frontTextColourId)
|| isColourSpecified (TabbedButtonBar::frontTextColourId)))
col = findColour (TabbedButtonBar::frontTextColourId);
else if (button.isColourSpecified (TabbedButtonBar::tabTextColourId)
|| isColourSpecified (TabbedButtonBar::tabTextColourId))
col = findColour (TabbedButtonBar::tabTextColourId);
else
col = button.getTabBackgroundColour().contrasting();
const float alpha = button.isEnabled() ? ((isMouseOver || isMouseDown) ? 1.0f : 0.8f) : 0.3f;
g.setColour (col.withMultipliedAlpha (alpha));
g.setFont (font);
g.addTransform (t);
g.drawFittedText (button.getButtonText().trim(),
0, 0, (int) length, (int) depth,
Justification::centred,
//jmax (1, ((int) depth) / 12), 0.5f);
1, 0.5f);
}
static Range<float> getBrightnessRange (const Image& im)
{
float minB = 1.0f, maxB = 0;
const int w = im.getWidth();
const int h = im.getHeight();
for (int y = 0; y < h; ++y)
{
for (int x = 0; x < w; ++x)
{
const float b = im.getPixelAt (x, y).getBrightness();
minB = jmin (minB, b);
maxB = jmax (maxB, b);
}
}
return Range<float> (minB, maxB);
}
Font CustomLookAndFeel::getLabelFont (Label& label)
{
if (fontScale == 1.0f) {
return label.getFont();
}
else {
return label.getFont().withHeight(label.getFont().getHeight() * fontScale);
}
}
void CustomLookAndFeel::drawLabel (Graphics& g, Label& label)
{
Colour olcolor = label.findColour (Label::backgroundColourId);
g.setColour(olcolor);
if (!olcolor.isTransparent()) {
if (labelCornerRadius > 0.0f) {
g.fillRoundedRectangle(label.getLocalBounds().reduced(1).toFloat(), labelCornerRadius);
} else {
g.fillAll (olcolor);
}
}
if (! label.isBeingEdited())
{
auto alpha = label.isEnabled() ? 1.0f : 0.5f;
const Font font (getLabelFont (label));
g.setColour (label.findColour (Label::textColourId).withMultipliedAlpha (alpha));
g.setFont (font);
auto textArea = getLabelBorderSize (label).subtractedFrom (label.getLocalBounds());
g.drawFittedText (label.getText(), textArea, label.getJustificationType(),
jmax (1, (int) (textArea.getHeight() / font.getHeight())),
label.getMinimumHorizontalScale());
olcolor = label.findColour (Label::outlineColourId).withMultipliedAlpha (alpha);
}
else if (label.isEnabled())
{
olcolor = label.findColour (Label::outlineColourId);
}
if (!olcolor.isTransparent()) {
g.setColour (olcolor);
if (labelCornerRadius > 0.0f) {
g.drawRoundedRectangle(label.getLocalBounds().reduced(1).toFloat(), labelCornerRadius, 1.0f);
} else {
g.drawRect (label.getLocalBounds());
}
}
}
Font CustomLookAndFeel::getTextButtonFont (TextButton& button, int buttonHeight)
{
// DBG("GetTextButton font with height: " << buttonHeight);
float textRatio = 0.5f;
//if (SonoTextButton* const textbutt = dynamic_cast<SonoTextButton*> (&button)) {
// textRatio = textbutt->getTextHeightRatio();
//}
return myFont.withHeight(jmin (16.0f, buttonHeight * textRatio) * fontScale);
}
Button* CustomLookAndFeel::createSliderButton (Slider&, const bool isIncrement)
{
TextButton * butt = new TextButton (isIncrement ? "+" : "-", {});
return butt;
}
Label* CustomLookAndFeel::createSliderTextBox (Slider& slider)
{
Label * lab = LookAndFeel_V4::createSliderTextBox(slider);
lab->setKeyboardType(TextInputTarget::decimalKeyboard);
lab->setFont(myFont.withHeight(16.0* fontScale));
lab->setMinimumHorizontalScale(0.5);
lab->setJustificationType(Justification::centredRight);
return lab;
}
Font CustomLookAndFeel::getSliderPopupFont (Slider&)
{
return Font (18.0f, Font::bold);
}
int CustomLookAndFeel::getSliderPopupPlacement (Slider&)
{
return BubbleComponent::above
//| BubbleComponent::below
| BubbleComponent::left
| BubbleComponent::right
;
}
void CustomLookAndFeel::drawButtonTextWithAlignment (Graphics& g, TextButton& button, bool /*isMouseOverButton*/, bool /*isButtonDown*/, Justification textjust)
{
Font font (getTextButtonFont (button, button.getHeight()));
g.setFont (font);
g.setColour (button.findColour (button.getToggleState() ? TextButton::textColourOnId
: TextButton::textColourOffId)
.withMultipliedAlpha (button.isEnabled() ? 1.0f : 0.5f));
float textRatio = 0.7f;
//if (SonoTextButton* const textbutt = dynamic_cast<SonoTextButton*> (&button)) {
// textRatio = textbutt->getTextHeightRatio();
//}
const int yIndent = jmin (2, button.proportionOfHeight ((1.0 - textRatio) * 0.5));
const int cornerSize = jmin (button.getHeight(), button.getWidth()) / 2;
const int fontHeight = roundToInt (font.getHeight() * 0.3);
const int leftIndent = jmin (fontHeight, 2 + cornerSize / (button.isConnectedOnLeft() ? 4 : 2));
const int rightIndent = jmin (fontHeight, 2 + cornerSize / (button.isConnectedOnRight() ? 4 : 2));
g.drawFittedText (button.getButtonText(),
leftIndent,
yIndent,
button.getWidth() - leftIndent - rightIndent,
button.getHeight() - yIndent * 2,
textjust, 2, 0.7f);
}
void CustomLookAndFeel::drawButtonText (Graphics& g, TextButton& button, bool isMouseOverButton, bool isButtonDown)
{
drawButtonTextWithAlignment(g, button, isMouseOverButton, isButtonDown);
}
void CustomLookAndFeel::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)
{
Component* const fileListComp = dynamic_cast<Component*> (&dcc);
if (isItemSelected)
g.fillAll (fileListComp != nullptr ? fileListComp->findColour (DirectoryContentsDisplayComponent::highlightColourId)
: findColour (DirectoryContentsDisplayComponent::highlightColourId));
int x = 32;
g.setColour (Colours::black);
if (isDirectory) {
if (icon != nullptr && icon->isValid())
{
g.drawImageWithin (*icon, 2, 2, x - 4, height - 4,
RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize,
false);
}
else
{
if (const Drawable* d = isDirectory ? getDefaultFolderImage()
: getDefaultDocumentFileImage())
d->drawWithin (g, Rectangle<float> (2.0f, 2.0f, x - 4.0f, height - 4.0f),
RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize, 1.0f);
}
}
else {
x = 4;
}
g.setColour (fileListComp != nullptr ? fileListComp->findColour (DirectoryContentsDisplayComponent::textColourId)
: findColour (DirectoryContentsDisplayComponent::textColourId));
g.setFont (myFont.withHeight(height * 0.6f));
if (width > 450 && ! isDirectory)
{
const int sizeX = roundToInt (width * 0.7f);
const int dateX = roundToInt (width * 0.8f);
g.drawFittedText (filename,
x, 0, sizeX - x, height,
Justification::centredLeft, 1);
g.setFont (myFont.withHeight(height * 0.6f));
g.setColour (Colours::darkgrey);
if (! isDirectory)
{
g.drawFittedText (fileSizeDescription,
sizeX, 0, dateX - sizeX - 8, height,
Justification::centredRight, 1);
g.drawFittedText (fileTimeDescription,
dateX, 0, width - 8 - dateX, height,
Justification::centredRight, 1);
}
}
else
{
g.drawFittedText (filename,
x, 0, width - x, height,
Justification::centredLeft, 1);
}
}
Button* CustomLookAndFeel::createFileBrowserGoUpButton()
{
DrawableButton* goUpButton = new DrawableButton ("up", DrawableButton::ImageOnButtonBackground);
Path arrowPath;
arrowPath.addArrow (Line<float> (50.0f, 100.0f, 50.0f, 0.0f), 40.0f, 100.0f, 50.0f);
DrawablePath arrowImage;
arrowImage.setFill (Colours::white.withAlpha (0.4f));
arrowImage.setPath (arrowPath);
goUpButton->setImages (&arrowImage);
return goUpButton;
}
void CustomLookAndFeel::layoutFileBrowserComponent (FileBrowserComponent& browserComp,
DirectoryContentsDisplayComponent* fileListComponent,
FilePreviewComponent* previewComp,
ComboBox* currentPathBox,
TextEditor* filenameBox,
Button* goUpButton)
{
const int x = 8;
int w = browserComp.getWidth() - x - x;
if (previewComp != nullptr)
{
const int previewWidth = w / 3;
previewComp->setBounds (x + w - previewWidth, 0, previewWidth, browserComp.getHeight());
w -= previewWidth + 4;
}
int y = 4;
const int controlsHeight = 22;
const int bottomSectionHeight = controlsHeight + 8;
const int upButtonWidth = 50;
currentPathBox->setBounds (x, y, w - upButtonWidth - 6, controlsHeight);
goUpButton->setBounds (x + w - upButtonWidth, y, upButtonWidth, controlsHeight);
y += controlsHeight + 4;
if (Component* const listAsComp = dynamic_cast <Component*> (fileListComponent))
{
listAsComp->setBounds (x, y, w, browserComp.getHeight() - y - bottomSectionHeight);
y = listAsComp->getBottom() + 4;
}
filenameBox->setBounds (x + 50, y, w - 50, controlsHeight);
}
PopupMenu::Options CustomLookAndFeel::getOptionsForComboBoxPopupMenu (ComboBox& box, Label& label)
{
auto options = PopupMenu::Options().withTargetComponent (&box)
.withItemThatMustBeVisible (box.getSelectedId())
.withMinimumWidth (box.getWidth())
.withMaximumNumColumns (1)
.withStandardItemHeight (label.getHeight());
#if JUCE_IOS || JUCE_ANDROID
auto * dw = box.findParentComponentOfClass<AudioProcessorEditor>();
if (dw) {
options = options.withParentComponent(dw);
}
#endif
return options;
}
void CustomLookAndFeel::drawTreeviewPlusMinusBox (Graphics& g, const Rectangle<float>& area,
Colour backgroundColour, bool isOpen, bool isMouseOver)
{
Path p;
p.addTriangle (0.0f, 0.0f, 1.0f, isOpen ? 0.0f : 0.5f, isOpen ? 0.5f : 0.0f, 1.0f);
DBG("draw plus minus ours");
//g.setColour (backgroundColour.contrasting().withAlpha (isMouseOver ? 0.5f : 0.3f));
g.setColour (Colours::white.withAlpha (isMouseOver ? 0.5f : 0.3f));
g.fillPath (p, p.getTransformToScaleToFit (area.reduced (2, area.getHeight() / 4), true));
}
void CustomLookAndFeel::drawToggleButton (Graphics& g, ToggleButton& button,
bool isMouseOverButton, bool isButtonDown)
{
/*
if (button.hasKeyboardFocus (true))
{
g.setColour (button.findColour (TextEditor::focusedOutlineColourId));
g.drawRect (0, 0, button.getWidth(), button.getHeight());
}
*/
float fontSize = jmin (15.0f, button.getHeight() * 0.75f) * fontScale;
const float tickWidth = fontSize * 1.1f;
drawTickBox (g, button, 4.0f, (button.getHeight() - tickWidth) * 0.5f,
tickWidth, tickWidth,
button.getToggleState(),
button.isEnabled(),
isMouseOverButton,
isButtonDown);
g.setColour (button.findColour (ToggleButton::textColourId));
g.setFont (myFont.withHeight(fontSize));
if (! button.isEnabled())
g.setOpacity (0.5f);
const int textX = (int) tickWidth + 10;
g.drawFittedText (button.getButtonText(),
textX, 0,
button.getWidth() - textX - 2, button.getHeight(),
Justification::centredLeft, 10);
}
void CustomLookAndFeel::drawTickBox (Graphics& g, Component& component,
float x, float y, float w, float h,
const bool ticked,
const bool isEnabled,
const bool isMouseOverButton,
const bool isButtonDown)
{
const float boxSize = w * 1.0f;
g.setColour (component.findColour (TextEditor::focusedOutlineColourId));
g.drawRect (x, y + (h - boxSize) * 0.5f, boxSize, boxSize);
if (ticked)
{
Path tick;
tick.startNewSubPath (1.5f, 3.0f);
tick.lineTo (3.0f, 6.0f);
tick.lineTo (6.0f, 0.0f);
g.setColour (isEnabled ? component.findColour(ToggleButton::tickColourId) : Colours::grey);
const AffineTransform trans (AffineTransform::scale (w / 9.0f, h / 9.0f)
.translated (x+2, y+1));
g.strokePath (tick, PathStrokeType (2.5f), trans);
}
}
void CustomLookAndFeel::drawRotarySlider (Graphics& g, int x, int y, int width, int height, float sliderPos,
const float rotaryStartAngle, const float rotaryEndAngle, Slider& slider)
{
const auto outline = findColour (Slider::rotarySliderOutlineColourId);
const auto fill = findColour (Slider::rotarySliderFillColourId);
const auto bounds = Rectangle<int> (x, y, width, height).toFloat().reduced (3);
auto radius = jmin (bounds.getWidth(), bounds.getHeight()) / 2.0f;
const auto toAngle = rotaryStartAngle + sliderPos * (rotaryEndAngle - rotaryStartAngle);
auto lineW = jmin (8.0f, radius * 0.3f);
auto arcRadius = radius - lineW * 0.5f;
Path backgroundArc;
backgroundArc.addCentredArc (bounds.getCentreX(),
bounds.getCentreY(),
arcRadius,
arcRadius,
0.0f,
rotaryStartAngle,
rotaryEndAngle,
true);
g.setColour (outline);
g.strokePath (backgroundArc, PathStrokeType (lineW, PathStrokeType::curved, PathStrokeType::rounded));
auto rotStartAngle = rotaryStartAngle;
if (slider.getProperties().contains ("fromCentre"))
{
rotStartAngle = (rotStartAngle + rotaryEndAngle) / 2;
}
if (slider.isEnabled())
{
Path valueArc;
valueArc.addCentredArc (bounds.getCentreX(),
bounds.getCentreY(),
arcRadius,
arcRadius,
0.0f,
rotStartAngle,
toAngle,
true);
g.setColour (fill);
g.strokePath (valueArc, PathStrokeType (lineW, PathStrokeType::curved, PathStrokeType::rounded));
}
const auto thumbWidth = lineW ; // * 1.5f;
const Point<float> thumbPoint (bounds.getCentreX() + arcRadius * std::cos (toAngle - float_Pi * 0.5f),
bounds.getCentreY() + arcRadius * std::sin (toAngle - float_Pi * 0.5f));
g.setColour (findColour (Slider::thumbColourId));
g.fillEllipse (Rectangle<float> (thumbWidth, thumbWidth).withCentre (thumbPoint));
}
//==============================================================================
int CustomLookAndFeel::getSliderThumbRadius (Slider& slider)
{
if (slider.isTwoValue() || slider.isThreeValue()) {
return jmin (14, slider.isHorizontal() ? static_cast<int> (slider.getHeight() * 0.25f)
: static_cast<int> (slider.getWidth() * 0.5f));
}
return jmin (16, slider.isHorizontal() ? static_cast<int> (slider.getHeight() * 0.5f)
: static_cast<int> (slider.getWidth() * 0.5f));
}
Slider::SliderLayout CustomLookAndFeel::getSliderLayout (Slider& slider)
{
// 1. compute the actually visible textBox size from the slider textBox size and some additional constraints
int minXSpace = 0;
int minYSpace = 0;
auto textBoxPos = slider.getTextBoxPosition();
if (textBoxPos == Slider::TextBoxLeft || textBoxPos == Slider::TextBoxRight)
minXSpace = 30;
else
minYSpace = 15;
auto localBounds = slider.getLocalBounds();
auto textBoxWidth = jmax (0, jmin (slider.getTextBoxWidth(), localBounds.getWidth() - minXSpace));
auto textBoxHeight = jmax (0, jmin (slider.getTextBoxHeight(), localBounds.getHeight() - minYSpace));
Slider::SliderLayout layout;
// 2. set the textBox bounds
if (textBoxPos != Slider::NoTextBox)
{
if (slider.isBar())
{
layout.textBoxBounds = localBounds;
}
else
{
layout.textBoxBounds.setWidth (textBoxWidth);
layout.textBoxBounds.setHeight (textBoxHeight);
const int thumbIndent = getSliderThumbRadius (slider);
if (textBoxPos == Slider::TextBoxLeft) layout.textBoxBounds.setX (0);
else if (textBoxPos == Slider::TextBoxRight) layout.textBoxBounds.setX (localBounds.getWidth() - textBoxWidth);
else if (sliderTextJustification.testFlags(Justification::right))/* above or below -> right */ layout.textBoxBounds.setX ((localBounds.getWidth() - textBoxWidth - 1));
else if (sliderTextJustification.testFlags(Justification::left))/* above or below -> left */ layout.textBoxBounds.setX (1);
else /* above or below -> centre horizontally */ layout.textBoxBounds.setX ((localBounds.getWidth() - textBoxWidth) / 2);
if (textBoxPos == Slider::TextBoxAbove) layout.textBoxBounds.setY (0);
else if (textBoxPos == Slider::TextBoxBelow) layout.textBoxBounds.setY (localBounds.getHeight() - textBoxHeight);
else if (sliderTextJustification.testFlags(Justification::top))/* left or right -> top */ layout.textBoxBounds.setY (0);
else if (sliderTextJustification.testFlags(Justification::bottom))/* left or right -> bottom */ layout.textBoxBounds.setY (localBounds.getHeight() - textBoxHeight);
else /* left or right -> centre vertically */ layout.textBoxBounds.setY ((localBounds.getHeight() - textBoxHeight) / 2);
}
}
// 3. set the slider bounds
layout.sliderBounds = localBounds;
if (slider.isBar())
{
layout.sliderBounds.reduce (1, 1); // bar border
}
else
{
if (textBoxPos == Slider::TextBoxLeft) layout.sliderBounds.removeFromLeft (textBoxWidth);
else if (textBoxPos == Slider::TextBoxRight) layout.sliderBounds.removeFromRight (textBoxWidth);
else if (textBoxPos == Slider::TextBoxAbove) layout.sliderBounds.removeFromTop (textBoxHeight);
else if (textBoxPos == Slider::TextBoxBelow) layout.sliderBounds.removeFromBottom (textBoxHeight);
const int thumbIndent = getSliderThumbRadius (slider);
if (slider.isHorizontal()) layout.sliderBounds.reduce (thumbIndent, 0);
else if (slider.isVertical()) layout.sliderBounds.reduce (0, thumbIndent);
}
return layout;
}
void CustomLookAndFeel::drawLinearSlider (Graphics& g, int x, int y, int width, int height,
float sliderPos,
float minSliderPos,
float maxSliderPos,
const Slider::SliderStyle style, Slider& slider)
{
if (slider.isBar())
{
if (slider.getProperties().contains ("fromCentre")) {
auto centrex = x + width*0.5f;
auto centrey = y + height*0.5f;
if (!slider.getProperties().contains ("noFill")) {
g.setColour (slider.findColour (Slider::trackColourId));
g.fillRect (slider.isHorizontal() ? Rectangle<float> (sliderPos > centrex ? centrex : sliderPos, y + 0.5f, sliderPos > centrex ? sliderPos - centrex : centrex - sliderPos, height - 1.0f)
: Rectangle<float> (x + 0.5f, sliderPos < centrey ? sliderPos : centrey, width - 1.0f, sliderPos < centrey ? centrey - sliderPos : sliderPos - centrey));
}
// draw line
g.setColour (slider.findColour (Slider::thumbColourId));
g.fillRect (slider.isHorizontal() ? Rectangle<float> (sliderPos - 1, y + 0.5f, 2, height - 1.0f)
: Rectangle<float> (x + 0.5f, sliderPos - 1, width - 1.0f, 2));
}
else {
if (!slider.getProperties().contains ("noFill")) {
g.setColour (slider.findColour (Slider::trackColourId));
g.fillRect (slider.isHorizontal() ? Rectangle<float> (static_cast<float> (x), y + 0.5f, sliderPos - x, height - 1.0f)
: Rectangle<float> (x + 0.5f, sliderPos, width - 1.0f, y + (height - sliderPos)));
}
//else
g.setColour (slider.findColour (Slider::thumbColourId));
{
// draw line
g.fillRect (slider.isHorizontal() ? Rectangle<float> (sliderPos - 1, y + 0.5f, 3, height - 1.0f)
: Rectangle<float> (x + 0.5f, sliderPos - 1, width - 1.0f, 3));
}
}
}
else
{
auto isTwoVal = (style == Slider::SliderStyle::TwoValueVertical || style == Slider::SliderStyle::TwoValueHorizontal);
auto isThreeVal = (style == Slider::SliderStyle::ThreeValueVertical || style == Slider::SliderStyle::ThreeValueHorizontal);
auto trackWidth = jmin (10.0f, slider.isHorizontal() ? height * 0.25f : width * 0.25f);
Point<float> startPoint (slider.isHorizontal() ? x : x + width * 0.5f,
slider.isHorizontal() ? y + height * 0.5f : height + y);
Point<float> endPoint (slider.isHorizontal() ? width + x : startPoint.x,
slider.isHorizontal() ? startPoint.y : y);
Path backgroundTrack;
backgroundTrack.startNewSubPath (startPoint);
backgroundTrack.lineTo (endPoint);
g.setColour (slider.findColour (Slider::backgroundColourId));
g.strokePath (backgroundTrack, { trackWidth, PathStrokeType::curved, PathStrokeType::rounded });
Path valueTrack;
Point<float> minPoint, maxPoint, thumbPoint;
if (isTwoVal || isThreeVal)
{
minPoint = { slider.isHorizontal() ? minSliderPos : width * 0.5f,
slider.isHorizontal() ? height * 0.5f : minSliderPos };
if (isThreeVal)
thumbPoint = { slider.isHorizontal() ? sliderPos : width * 0.5f,
slider.isHorizontal() ? height * 0.5f : sliderPos };
maxPoint = { slider.isHorizontal() ? maxSliderPos : width * 0.5f,
slider.isHorizontal() ? height * 0.5f : maxSliderPos };
}
else
{
auto kx = slider.isHorizontal() ? sliderPos : (x + width * 0.5f);
auto ky = slider.isHorizontal() ? (y + height * 0.5f) : sliderPos;
minPoint = startPoint;
maxPoint = { kx, ky };
}
auto thumbWidth = getSliderThumbRadius (slider);
valueTrack.startNewSubPath (minPoint);
valueTrack.lineTo (isThreeVal ? thumbPoint : maxPoint);
g.setColour (slider.findColour (Slider::trackColourId));
g.strokePath (valueTrack, { trackWidth, PathStrokeType::curved, PathStrokeType::rounded });
if (! isTwoVal)
{
g.setColour (slider.findColour (Slider::thumbColourId));
g.fillEllipse (Rectangle<float> (static_cast<float> (thumbWidth), static_cast<float> (thumbWidth)).withCentre (isThreeVal ? thumbPoint : maxPoint));
}
if (isTwoVal || isThreeVal)
{
auto sr = jmin (trackWidth, (slider.isHorizontal() ? height : width) * 0.4f);
auto pointerColour = slider.findColour (Slider::thumbColourId);
auto wscale = 1.5f;
if (slider.isHorizontal())
{
/*
drawPointer (g, minSliderPos - sr,
height * 0.5f - trackWidth*wscale*0.5, //jmax (0.0f, y + height * 0.5f - trackWidth * 0.5f),
trackWidth * wscale, pointerColour, 1); // 2
drawPointer (g, maxSliderPos - trackWidth,
height * 0.5f - trackWidth*wscale*0.5, //jmin (y + height - trackWidth * 2.0f, (float)y + height * 0.5f),
trackWidth * wscale, pointerColour, 3); // 4
*/
drawPointer (g, minSliderPos - sr,
jmax (0.0f, y + height * 0.5f - trackWidth * wscale),
trackWidth * wscale, pointerColour, 2); // 2
drawPointer (g, maxSliderPos - trackWidth*0.5*wscale,
jmin (y + height - trackWidth * wscale, (float)y + height * 0.5f),
trackWidth * wscale, pointerColour, 4); // 4
}
else
{
drawPointer (g, jmax (0.0f, x + width * 0.5f - trackWidth * 2.0f),
minSliderPos - trackWidth,
trackWidth * wscale, pointerColour, 1);
drawPointer (g, jmin (x + width - trackWidth * 2.0f, x + width * 0.5f), maxSliderPos - sr,
trackWidth * wscale, pointerColour, 3);
}
}
}
}
void CustomLookAndFeel::drawDrawableButton (Graphics& g, DrawableButton& button,
bool isMouseOverButton, bool isButtonDown)
{
const auto cornerSize = 6.0f;
bool toggleState = button.getToggleState();
;
//Rectangle<float> bounds = g.getClipBounds().toFloat();
Rectangle<float> bounds = button.getLocalBounds().toFloat();
g.setColour(button.findColour (toggleState ? DrawableButton::backgroundOnColourId
: DrawableButton::backgroundColourId));
//g.fillAll();
g.fillRoundedRectangle(bounds, cornerSize);
if (isButtonDown) {
//setColour (SonoDrawableButton::overOverlayColourId, Colour::fromFloatRGBA(0.8, 0.8, 0.8, 0.08));
//setColour (SonoDrawableButton::downOverlayColourId, Colour::fromFloatRGBA(0.8, 0.8, 0.8, 0.3));
g.setColour(Colour::fromFloatRGBA(0.8, 0.8, 0.8, 0.3));
//g.setColour(findColour(SonoDrawableButton::downOverlayColourId));
//g.fillAll();
g.fillRoundedRectangle(bounds, cornerSize);
}
else if (isMouseOverButton) {
//g.setColour(findColour(SonoDrawableButton::overOverlayColourId));
g.setColour(Colour::fromFloatRGBA(0.8, 0.8, 0.8, 0.08));
//g.fillAll();
g.fillRoundedRectangle(bounds, cornerSize);
}
//g.fillAll (button.findColour (toggleState ? DrawableButton::backgroundOnColourId
// : DrawableButton::backgroundColourId));
int textH = 0;
int textW = 0;
float imageratio = 0.75f;
//if (SonoDrawableButton* const sonobutt = dynamic_cast<SonoDrawableButton*> (&button)) {
// imageratio = sonobutt->getForegroundImageRatio();
//}
if (button.getStyle() == DrawableButton::ImageAboveTextLabel || button.getStyle() == DrawableButton::ImageBelowTextLabel) {
textH = jmin (14, button.proportionOfHeight (0.2f));
} else if (button.getStyle() == DrawableButton::ImageLeftOfTextLabel || button.getStyle() == DrawableButton::ImageRightOfTextLabel) {
textH = jmin (14, button.proportionOfHeight (0.8f));
textW = jmax (20, button.proportionOfWidth (1.0f - imageratio));
}
if (textH > 0)
{
g.setFont (myFont.withHeight((float) textH * fontScale));
g.setColour (button.findColour (toggleState ? DrawableButton::textColourOnId
: DrawableButton::textColourId)
.withMultipliedAlpha (button.isEnabled() ? 1.0f : 0.4f));
if (button.getStyle() == DrawableButton::ImageAboveTextLabel) {
g.drawFittedText (button.getButtonText(),
2, button.getHeight() - textH - 1,
button.getWidth() - 4, textH,
Justification::centred, 1);
}
else if (button.getStyle() == DrawableButton::ImageBelowTextLabel) {
g.drawFittedText (button.getButtonText(),
2, 1,
button.getWidth() - 4, textH,
Justification::centred, 1);
}
else if (button.getStyle() == DrawableButton::ImageRightOfTextLabel) {
g.drawFittedText (button.getButtonText(),
2, 1,
textW , button.getHeight() - 2,
Justification::centred, 2, 0.6f);
}
else if (button.getStyle() == DrawableButton::ImageLeftOfTextLabel) {
g.drawFittedText (button.getButtonText(),
button.getWidth() - textW - 4 , 1,
textW , button.getHeight() - 2,
Justification::centred, 2, 0.6f);
}
}
}
void CustomLookAndFeel::drawBubble (Graphics& g, BubbleComponent& comp,
const Point<float>& tip, const Rectangle<float>& body)
{
Path p;
p.addBubble (body.reduced (0.5f), body.getUnion (Rectangle<float> (tip.x, tip.y, 1.0f, 1.0f)),
tip, 5.0f, jmin (10.0f, body.getWidth() * 0.2f, body.getHeight() * 0.2f));
g.setColour (comp.findColour (BubbleComponent::backgroundColourId));
g.fillPath (p);
g.setColour (comp.findColour (BubbleComponent::outlineColourId));
g.strokePath (p, PathStrokeType (1.0f));
}
CustomBigTextLookAndFeel::CustomBigTextLookAndFeel(float maxTextSize)
: maxSize(maxTextSize)
{
}
Font CustomBigTextLookAndFeel::getTextButtonFont (TextButton& button, int buttonHeight)
{
// DBG("GetTextButton font with height: " << buttonHeight << " maxsize: " << maxSize);
float textRatio = 0.8f;
//if (SonoTextButton* const textbutt = dynamic_cast<SonoTextButton*> (&button)) {
// textRatio = textbutt->getTextHeightRatio();
//}
return myFont.withHeight(jmin (maxSize, buttonHeight * textRatio) * fontScale);
}
Label* CustomBigTextLookAndFeel::createSliderTextBox (Slider& slider)
{
Label * lab = LookAndFeel_V4::createSliderTextBox(slider);
lab->setKeyboardType(TextInputTarget::decimalKeyboard);
lab->setFont(myFont.withHeight(maxSize * fontScale));
lab->setJustificationType(textJustification);
lab->setMinimumHorizontalScale(0.5);
return lab;
}
Button* CustomBigTextLookAndFeel::createSliderButton (Slider&, const bool isIncrement)
{
TextButton * butt = new TextButton (isIncrement ? "+" : "-", {});
butt->setLookAndFeel(this);
return butt;
}
void CustomBigTextLookAndFeel::drawToggleButton (Graphics& g, ToggleButton& button,
bool isMouseOverButton, bool isButtonDown)
{
/*
if (button.hasKeyboardFocus (true))
{
g.setColour (button.findColour (TextEditor::focusedOutlineColourId));
g.drawRect (0, 0, button.getWidth(), button.getHeight());
}
*/
float fontSize = jmin (maxSize, button.getHeight() * 0.75f) * fontScale;
const float tickWidth = fontSize * 1.1f;
drawTickBox (g, button, 4.0f, (button.getHeight() - tickWidth) * 0.5f,
tickWidth, tickWidth,
button.getToggleState(),
button.isEnabled(),
isMouseOverButton,
isButtonDown);
g.setColour (button.findColour (ToggleButton::textColourId));
g.setFont (myFont.withHeight(fontSize));
if (! button.isEnabled())
g.setOpacity (0.5f);
const int textX = (int) tickWidth + 10;
g.drawFittedText (button.getButtonText(),
textX, 0,
button.getWidth() - textX - 2, button.getHeight(),
Justification::centredLeft, 10);
}