Files
paulxstretch/Source/CustomLookAndFeel.cpp
Nikolai Rodionov c4fc6ef30a Build with JUCE 7.0.2
Update build and changelog

Switch to docker runners

Fix the source path in build

Fix the release path in build

Use zipped artifacts

build: Install zip

build: Fix commands for the package step

build: Fix zip command

update a bit

Signed-off-by: Nikolai Rodionov <allanger@badhouseplants.net>
2025-07-05 09:43:52 +02:00

1317 lines
52 KiB
C++

// 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));
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 (0xdde9e9e9));
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));
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;
float xhscale = 0.6f;
#if JUCE_IOS
hscale = 0.5f;
xhscale = 0.5f;
#endif
float fontsize = button.getExtraComponent() != nullptr ? jmin(depth, 32.0f) * xhscale : 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 (MathConstants<float>::pi * -0.5f).translated (area.getX(), area.getBottom()); break;
case TabbedButtonBar::TabsAtRight: t = t.rotated (MathConstants<float>::pi * 0.5f).translated (area.getRight(), area.getY()); break;
case TabbedButtonBar::TabsAtTop:
case TabbedButtonBar::TabsAtBottom: t = t.translated (area.getX(), area.getY()); break;
default: jassertfalse; break;
}
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 (MathConstants<float>::pi * -0.5f).translated (area.getX(), area.getBottom()); break;
case TabbedButtonBar::TabsAtRight: t = t.rotated (MathConstants<float>::pi * 0.5f).translated (area.getRight(), area.getY()); break;
case TabbedButtonBar::TabsAtTop:
case TabbedButtonBar::TabsAtBottom: t = t.translated (area.getX(), area.getY()); break;
default: jassertfalse; break;
}
Colour col;
if (button.isFrontTab() && (button.isColourSpecified (TabbedButtonBar::frontTextColourId)
|| isColourSpecified (TabbedButtonBar::frontTextColourId)))
col = findColour (TabbedButtonBar::frontTextColourId);
else if (button.isColourSpecified (TabbedButtonBar::tabTextColourId)
|| isColourSpecified (TabbedButtonBar::tabTextColourId))
col = findColour (TabbedButtonBar::tabTextColourId);
else
col = button.getTabBackgroundColour().contrasting();
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 - MathConstants<float>::pi * 0.5f),
bounds.getCentreY() + arcRadius * std::sin (toAngle - MathConstants<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.85f;
//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);
}