#include "HorizontLookAndFeel.h" namespace { const juce::Colour tealAccent (0xFF3CE0C8); const juce::Colour textMain (0xFFE8F6F4); const juce::Colour textDim (0xFFB8CCCC); const juce::Colour charcoal (0xFF0B0E10); } HorizontLookAndFeel::HorizontLookAndFeel() { setColour (juce::ComboBox::outlineColourId, juce::Colour (0xFF2A3A3D)); setColour (juce::ComboBox::textColourId, textMain); setColour (juce::ComboBox::arrowColourId, tealAccent); setColour (juce::PopupMenu::backgroundColourId, juce::Colour (0xFF141B1E)); setColour (juce::PopupMenu::highlightedBackgroundColourId, juce::Colour (0xFF1E3A3C)); setColour (juce::PopupMenu::textColourId, textMain); setColour (juce::TooltipWindow::textColourId, textMain); setColour (juce::TooltipWindow::backgroundColourId, juce::Colour (0xFF122A2B)); setColour (juce::TooltipWindow::outlineColourId, tealAccent); } void HorizontLookAndFeel::drawRotarySlider (juce::Graphics& g, int x, int y, int width, int height, float sliderPos, float rotaryStartAngle, float rotaryEndAngle, juce::Slider&) { const auto bounds = juce::Rectangle ((float) x, (float) y, (float) width, (float) height); const auto centre = bounds.getCentre(); const float radius = jmin (bounds.getWidth(), bounds.getHeight()) * 0.5f; const float angle = rotaryStartAngle + sliderPos * (rotaryEndAngle - rotaryStartAngle); { auto shadow = bounds.translated (0.0f, radius * 0.10f); auto grad = juce::ColourGradient (juce::Colour (0x80000000), centre.withY (centre.getY() + radius * 0.45f), juce::Colour (0x00000000), centre.withY (centre.getY() + radius * 0.45f).translated (radius * 1.1f, 0.0f), true); grad.addColour (0.55f, juce::Colour (0x30000000)); g.setGradientFill (grad); g.fillEllipse (shadow); } { auto disc = bounds.reduced (radius * 0.05f); auto grad = juce::ColourGradient (juce::Colour (0xFFA9BBC2), centre.translated (-radius * 0.35f, -radius * 0.45f), juce::Colour (0xFF171B1E), centre.translated (-radius * 0.35f, -radius * 0.45f).translated (radius * 1.25f, 0.0f), true); grad.addColour (0.35f, juce::Colour (0xFF6E7C84)); grad.addColour (0.75f, juce::Colour (0xFF3A4247)); g.setGradientFill (grad); g.fillEllipse (disc); } { auto rim = bounds.reduced (radius * 0.03f); g.setColour (charcoal); g.drawEllipse (rim, jmax (1.0f, radius * 0.05f)); } { auto face = bounds.reduced (radius * 0.24f); auto grad = juce::ColourGradient (juce::Colour (0xFF333C43), centre.translated (0.0f, -radius * 0.10f), juce::Colour (0xFF101316), centre.translated (0.0f, -radius * 0.10f).translated (radius * 0.85f, 0.0f), true); grad.addColour (0.55f, juce::Colour (0xFF20262B)); g.setGradientFill (grad); g.fillEllipse (face); g.setColour (juce::Colour (0x383CE0C8)); g.drawEllipse (face, 1.0f); } { const float tipDist = radius * 0.72f; const float baseDist = radius * 0.34f; const float halfWidth = radius * 0.085f; const auto tip = centre.getPointOnCircumference (tipDist, angle); const auto base = centre.getPointOnCircumference (baseDist, angle); const float perp = angle + juce::MathConstants::halfPi; const auto b1 = base.translated (std::cos (perp) * halfWidth, std::sin (perp) * halfWidth); const auto b2 = base.translated (-std::cos (perp) * halfWidth, -std::sin (perp) * halfWidth); juce::Path notch; notch.addTriangle (b1, b2, tip); notch.closeSubPath(); g.setColour (tealAccent); g.fillPath (notch); g.setColour (tealAccent); g.strokePath (notch, juce::PathStrokeType (1.0f)); } { auto hl = juce::Rectangle (radius * 0.9f, radius * 0.5f) .withCentre (centre.translated (-radius * 0.28f, -radius * 0.32f)); auto grad = juce::ColourGradient (juce::Colour (0x30FFFFFF), hl.getCentre(), juce::Colour (0x00FFFFFF), hl.getCentre().translated (radius * 0.6f, 0.0f), true); g.setGradientFill (grad); g.fillEllipse (hl); } { auto dot = juce::Rectangle (radius * 0.16f, radius * 0.16f).withCentre (centre); auto grad = juce::ColourGradient (juce::Colour (0xFF5A666D), centre.translated (-radius * 0.03f, -radius * 0.03f), juce::Colour (0xFF171B1E), centre.translated (-radius * 0.03f, -radius * 0.03f).translated (radius * 0.14f, 0.0f), true); g.setGradientFill (grad); g.fillEllipse (dot); } } void HorizontLookAndFeel::drawComboBox (juce::Graphics& g, int width, int height, bool, int buttonX, int buttonY, int buttonW, int buttonH, juce::ComboBox&) { auto bounds = juce::Rectangle (0, 0, (float) width, (float) height); auto grad = juce::ColourGradient (juce::Colour (0xFF22292E), { 0.0f, 0.0f }, juce::Colour (0xFF0E1215), { 0.0f, (float) height }, false); g.setGradientFill (grad); g.fillRoundedRectangle (bounds, 4.0f); g.setColour (juce::Colour (0xFF3A4A4D)); g.drawRoundedRectangle (bounds.reduced (0.5f), 4.0f, 1.0f); auto arrowArea = juce::Rectangle ((float) buttonX, (float) buttonY, (float) buttonW, (float) buttonH); juce::Path arrow; arrow.startNewSubPath (arrowArea.getX() + arrowArea.getWidth() * 0.35f, arrowArea.getCentreY() - 2.0f); arrow.lineTo (arrowArea.getCentreX(), arrowArea.getCentreY() + 3.0f); arrow.lineTo (arrowArea.getX() + arrowArea.getWidth() * 0.65f, arrowArea.getCentreY() - 2.0f); g.setColour (tealAccent); g.strokePath (arrow, juce::PathStrokeType (1.6f, juce::PathStrokeType::JointStyle::beveled, juce::PathStrokeType::EndCapStyle::rounded)); } void HorizontLookAndFeel::drawPopupMenuBackground (juce::Graphics& g, int width, int height) { g.setColour (juce::Colour (0xF0141B1E)); g.fillRoundedRectangle (0.0f, 0.0f, (float) width, (float) height, 6.0f); g.setColour (juce::Colour (0xFF3A4A4D)); g.drawRoundedRectangle (0.5f, 0.5f, (float) width - 1.0f, (float) height - 1.0f, 6.0f, 1.0f); } void HorizontLookAndFeel::drawPopupMenuItem (juce::Graphics& g, const juce::Rectangle& area, bool isSeparator, bool isActive, bool isHighlighted, bool isTicked, bool, const juce::String& text, const juce::String&, const juce::Drawable*, const juce::Colour* textColour) { if (isSeparator) { auto r = area.reduced (5, 0); g.setColour (juce::Colour (0x334A5A5D)); g.fillRect (r.removeFromBottom (1)); return; } if (isHighlighted && isActive) { g.setColour (juce::Colour (0xFF1E3A3C)); g.fillRoundedRectangle (area.toFloat().reduced (2.0f), 4.0f); } auto textArea = area.reduced (12, 0); if (isTicked) textArea.removeFromLeft (12); g.setColour (isActive ? (textColour != nullptr ? *textColour : textMain) : textDim); g.setFont (juce::Font (juce::FontOptions (13.0f))); g.drawText (text, textArea, juce::Justification::centredLeft, false); if (isTicked) { auto dot = juce::Rectangle (4.0f, 4.0f) .withCentre (juce::Point ((float) (area.getX() + 10), (float) area.getCentreY())); g.setColour (tealAccent); g.fillEllipse (dot); } } void HorizontLookAndFeel::drawTooltip (juce::Graphics& g, const juce::String& text, int width, int height) { g.setColour (juce::Colour (0xF0122A2B)); g.fillRoundedRectangle (0.0f, 0.0f, (float) width, (float) height, 4.0f); g.setColour (tealAccent); g.drawRoundedRectangle (0.5f, 0.5f, (float) width - 1.0f, (float) height - 1.0f, 4.0f, 1.0f); g.setColour (textMain); g.setFont (juce::Font (juce::FontOptions (12.0f))); g.drawText (text, juce::Rectangle (6, 0, width - 12, height), juce::Justification::centred, true); }