2023-07-28 20:10:21 +00:00
|
|
|
#include "LookAndFeel.h"
|
2024-03-03 20:30:58 +00:00
|
|
|
#include "components/SwitchButton.h"
|
2023-07-28 20:10:21 +00:00
|
|
|
|
|
|
|
OscirenderLookAndFeel::OscirenderLookAndFeel() {
|
2023-12-18 13:41:56 +00:00
|
|
|
// slider
|
2023-07-28 20:10:21 +00:00
|
|
|
setColour(juce::Slider::thumbColourId, Colours::veryDark);
|
2024-03-18 23:06:14 +00:00
|
|
|
setColour(juce::Slider::textBoxOutlineColourId, Colours::veryDark);
|
2023-07-28 20:10:21 +00:00
|
|
|
setColour(juce::Slider::textBoxBackgroundColourId, Colours::veryDark);
|
|
|
|
setColour(juce::Slider::textBoxHighlightColourId, Colours::accentColor.withMultipliedAlpha(0.5));
|
|
|
|
setColour(juce::Slider::trackColourId, juce::Colours::grey);
|
|
|
|
setColour(juce::Slider::backgroundColourId, Colours::dark);
|
|
|
|
setColour(sliderThumbOutlineColourId, juce::Colours::white);
|
2023-12-18 13:41:56 +00:00
|
|
|
|
|
|
|
// buttons
|
|
|
|
setColour(juce::TextButton::buttonColourId, Colours::veryDark);
|
2024-03-03 20:30:58 +00:00
|
|
|
setColour(jux::SwitchButton::switchColour, juce::Colours::white);
|
|
|
|
setColour(jux::SwitchButton::switchOnBackgroundColour, Colours::accentColor);
|
2024-04-04 19:47:52 +00:00
|
|
|
setColour(jux::SwitchButton::switchOffBackgroundColour, Colours::grey);
|
2023-12-18 13:41:56 +00:00
|
|
|
|
|
|
|
// windows & menus
|
|
|
|
setColour(juce::ResizableWindow::backgroundColourId, Colours::grey);
|
2023-07-28 20:10:21 +00:00
|
|
|
setColour(groupComponentBackgroundColourId, Colours::darker);
|
|
|
|
setColour(groupComponentHeaderColourId, Colours::veryDark);
|
2024-03-29 21:53:48 +00:00
|
|
|
setColour(juce::PopupMenu::backgroundColourId, Colours::darker);
|
|
|
|
setColour(juce::PopupMenu::highlightedBackgroundColourId, Colours::grey);
|
|
|
|
setColour(juce::TooltipWindow::backgroundColourId, Colours::darker);
|
2023-12-18 13:41:56 +00:00
|
|
|
setColour(juce::TooltipWindow::outlineColourId, juce::Colours::white);
|
2023-12-21 16:18:34 +00:00
|
|
|
setColour(juce::TextButton::buttonOnColourId, Colours::darker);
|
2024-11-30 21:11:49 +00:00
|
|
|
setColour(juce::AlertWindow::outlineColourId, Colours::darker);
|
|
|
|
setColour(juce::AlertWindow::backgroundColourId, Colours::darker);
|
2023-12-18 13:41:56 +00:00
|
|
|
|
|
|
|
// combo box
|
2023-07-28 20:10:21 +00:00
|
|
|
setColour(juce::ComboBox::backgroundColourId, Colours::veryDark);
|
2024-03-18 20:27:31 +00:00
|
|
|
setColour(juce::ComboBox::outlineColourId, Colours::veryDark);
|
2023-07-28 20:10:21 +00:00
|
|
|
setColour(juce::ComboBox::arrowColourId, juce::Colours::white);
|
2023-12-18 13:41:56 +00:00
|
|
|
|
|
|
|
// text box
|
2023-07-28 20:10:21 +00:00
|
|
|
setColour(juce::TextEditor::backgroundColourId, Colours::veryDark);
|
2024-03-18 23:06:14 +00:00
|
|
|
setColour(juce::TextEditor::outlineColourId, Colours::veryDark);
|
|
|
|
setColour(juce::TextEditor::focusedOutlineColourId, Colours::accentColor);
|
2023-12-18 13:41:56 +00:00
|
|
|
setColour(juce::CaretComponent::caretColourId, Dracula::foreground);
|
|
|
|
setColour(juce::TextEditor::highlightColourId, Colours::grey);
|
|
|
|
|
|
|
|
// list box
|
2023-07-28 20:10:21 +00:00
|
|
|
setColour(juce::ListBox::backgroundColourId, Colours::darker);
|
2023-12-18 13:41:56 +00:00
|
|
|
|
|
|
|
// scroll bar
|
2023-07-28 20:10:21 +00:00
|
|
|
setColour(juce::ScrollBar::thumbColourId, juce::Colours::white);
|
|
|
|
setColour(juce::ScrollBar::trackColourId, Colours::veryDark);
|
|
|
|
setColour(juce::ScrollBar::backgroundColourId, Colours::veryDark);
|
2023-12-18 13:41:56 +00:00
|
|
|
|
|
|
|
// custom components
|
2023-07-28 20:10:21 +00:00
|
|
|
setColour(effectComponentBackgroundColourId, juce::Colours::transparentBlack);
|
|
|
|
setColour(effectComponentHandleColourId, Colours::veryDark);
|
2023-12-18 13:41:56 +00:00
|
|
|
|
|
|
|
// code editor
|
2023-07-28 21:14:06 +00:00
|
|
|
setColour(juce::CodeEditorComponent::backgroundColourId, Colours::darker);
|
2023-08-27 16:47:30 +00:00
|
|
|
setColour(juce::CodeEditorComponent::defaultTextColourId, Dracula::foreground);
|
2023-07-28 21:14:06 +00:00
|
|
|
setColour(juce::CodeEditorComponent::lineNumberBackgroundId, Colours::veryDark);
|
2023-08-27 16:47:30 +00:00
|
|
|
setColour(juce::CodeEditorComponent::lineNumberTextId, Dracula::foreground);
|
|
|
|
setColour(juce::CodeEditorComponent::highlightColourId, Colours::grey);
|
2023-07-28 21:14:06 +00:00
|
|
|
|
2023-12-18 13:41:56 +00:00
|
|
|
// envelope
|
2023-12-18 15:06:34 +00:00
|
|
|
setColour(EnvelopeComponent::Node, Colours::veryDark);
|
|
|
|
setColour(EnvelopeComponent::ReleaseNode, Colours::veryDark);
|
|
|
|
setColour(EnvelopeComponent::LoopNode, Colours::veryDark);
|
|
|
|
setColour(EnvelopeComponent::NodeOutline, juce::Colours::white);
|
2023-12-18 13:41:56 +00:00
|
|
|
setColour(EnvelopeComponent::Line, juce::Colours::white);
|
|
|
|
setColour(EnvelopeComponent::LoopLine, juce::Colours::white);
|
|
|
|
setColour(EnvelopeComponent::Background, Colours::veryDark);
|
|
|
|
setColour(EnvelopeComponent::GridLine, Colours::dark);
|
|
|
|
setColour(EnvelopeComponent::LegendText, juce::Colours::white);
|
|
|
|
setColour(EnvelopeComponent::LegendBackground, Colours::veryDark);
|
2023-12-21 15:17:08 +00:00
|
|
|
setColour(EnvelopeComponent::LineBackground, juce::Colours::white);
|
2023-12-18 13:41:56 +00:00
|
|
|
|
|
|
|
// midi keyboard
|
|
|
|
setColour(juce::MidiKeyboardComponent::blackNoteColourId, Colours::veryDark);
|
|
|
|
setColour(juce::MidiKeyboardComponent::whiteNoteColourId, juce::Colours::white);
|
|
|
|
setColour(juce::MidiKeyboardComponent::mouseOverKeyOverlayColourId, Colours::accentColor.withAlpha(0.3f));
|
|
|
|
setColour(juce::MidiKeyboardComponent::keyDownOverlayColourId, Colours::accentColor.withAlpha(0.7f));
|
|
|
|
setColour(juce::MidiKeyboardComponent::shadowColourId, juce::Colours::transparentBlack);
|
|
|
|
setColour(juce::MidiKeyboardComponent::upDownButtonBackgroundColourId, Colours::veryDark);
|
|
|
|
setColour(juce::MidiKeyboardComponent::upDownButtonArrowColourId, juce::Colours::white);
|
2024-11-30 21:11:49 +00:00
|
|
|
|
|
|
|
// progress bar
|
|
|
|
setColour(juce::ProgressBar::backgroundColourId, juce::Colours::transparentBlack);
|
|
|
|
setColour(juce::ProgressBar::foregroundColourId, Colours::accentColor);
|
2023-12-18 13:41:56 +00:00
|
|
|
|
|
|
|
// UI colours
|
2023-07-28 20:10:21 +00:00
|
|
|
getCurrentColourScheme().setUIColour(ColourScheme::widgetBackground, Colours::veryDark);
|
2023-11-25 22:10:36 +00:00
|
|
|
getCurrentColourScheme().setUIColour(ColourScheme::UIColour::defaultFill, Colours::accentColor);
|
2023-12-21 16:18:34 +00:00
|
|
|
|
|
|
|
// I have to do this, otherwise components are initialised before the look and feel is set
|
|
|
|
juce::LookAndFeel::setDefaultLookAndFeel(this);
|
2023-07-28 20:10:21 +00:00
|
|
|
}
|
|
|
|
|
2024-03-18 23:06:14 +00:00
|
|
|
void OscirenderLookAndFeel::drawLabel(juce::Graphics& g, juce::Label& label) {
|
2024-03-27 20:21:55 +00:00
|
|
|
label.setRepaintsOnMouseActivity(true);
|
|
|
|
auto baseColour = label.findColour(juce::Label::backgroundColourId);
|
|
|
|
if (label.isEditable()) {
|
|
|
|
baseColour = LookAndFeelHelpers::createBaseColour(baseColour, false, label.isMouseOver(true), false, label.isEnabled());
|
|
|
|
}
|
|
|
|
g.setColour(baseColour);
|
2024-03-18 23:06:14 +00:00
|
|
|
g.fillRoundedRectangle(label.getLocalBounds().toFloat(), RECT_RADIUS);
|
|
|
|
|
|
|
|
if (! label.isBeingEdited())
|
|
|
|
{
|
|
|
|
auto alpha = label.isEnabled() ? 1.0f : 0.5f;
|
|
|
|
const juce::Font font (getLabelFont (label));
|
|
|
|
|
|
|
|
g.setColour (label.findColour (juce::Label::textColourId).withMultipliedAlpha (alpha));
|
|
|
|
g.setFont (font);
|
|
|
|
|
|
|
|
auto textArea = getLabelBorderSize (label).subtractedFrom (label.getLocalBounds());
|
|
|
|
|
|
|
|
g.drawFittedText (label.getText(), textArea, label.getJustificationType(),
|
|
|
|
juce::jmax (1, (int) ((float) textArea.getHeight() / font.getHeight())),
|
|
|
|
label.getMinimumHorizontalScale());
|
|
|
|
|
|
|
|
g.setColour (label.findColour (juce::Label::outlineColourId).withMultipliedAlpha (alpha));
|
|
|
|
}
|
|
|
|
else if (label.isEnabled())
|
|
|
|
{
|
2024-03-27 20:21:55 +00:00
|
|
|
auto outlineColour = label.findColour(juce::Label::outlineColourId);
|
|
|
|
if (label.isEditable()) {
|
|
|
|
outlineColour = LookAndFeelHelpers::createBaseColour(outlineColour, false, label.isMouseOver(true), false, label.isEnabled());
|
|
|
|
}
|
|
|
|
g.setColour(outlineColour);
|
|
|
|
g.drawRoundedRectangle(label.getLocalBounds().toFloat(), RECT_RADIUS, 1);
|
2024-03-18 23:06:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OscirenderLookAndFeel::fillTextEditorBackground(juce::Graphics& g, int width, int height, juce::TextEditor& textEditor) {
|
2024-03-27 20:21:55 +00:00
|
|
|
textEditor.setRepaintsOnMouseActivity(true);
|
2024-03-18 23:06:14 +00:00
|
|
|
if (dynamic_cast<juce::AlertWindow*> (textEditor.getParentComponent()) != nullptr)
|
|
|
|
{
|
|
|
|
g.setColour (textEditor.findColour (juce::TextEditor::backgroundColourId));
|
|
|
|
g.fillRect (0, 0, width, height);
|
|
|
|
|
|
|
|
g.setColour (textEditor.findColour (juce::TextEditor::outlineColourId));
|
|
|
|
g.drawHorizontalLine (height - 1, 0.0f, static_cast<float> (width));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2024-03-27 20:21:55 +00:00
|
|
|
auto backgroundColour = textEditor.findColour (juce::TextEditor::backgroundColourId);
|
|
|
|
auto baseColour = LookAndFeelHelpers::createBaseColour(backgroundColour, false, textEditor.isMouseOver(true), false, textEditor.isEnabled());
|
|
|
|
g.setColour(baseColour);
|
2024-03-18 23:06:14 +00:00
|
|
|
g.fillRoundedRectangle(textEditor.getLocalBounds().toFloat(), RECT_RADIUS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OscirenderLookAndFeel::drawTextEditorOutline(juce::Graphics& g, int width, int height, juce::TextEditor& textEditor) {
|
|
|
|
if (textEditor.isEnabled())
|
|
|
|
{
|
|
|
|
if (textEditor.hasKeyboardFocus (true) && ! textEditor.isReadOnly())
|
|
|
|
{
|
|
|
|
const int border = 2;
|
|
|
|
|
|
|
|
g.setColour (textEditor.findColour (juce::TextEditor::focusedOutlineColourId));
|
|
|
|
g.drawRoundedRectangle(0, 0, width, height, RECT_RADIUS, border);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2024-03-27 20:21:55 +00:00
|
|
|
auto outlineColour = textEditor.findColour(juce::TextEditor::outlineColourId);
|
|
|
|
outlineColour = LookAndFeelHelpers::createBaseColour(outlineColour, false, textEditor.isMouseOver(true), false, textEditor.isEnabled());
|
|
|
|
g.setColour(outlineColour);
|
2024-03-18 23:06:14 +00:00
|
|
|
g.drawRoundedRectangle(0, 0, width, height, RECT_RADIUS, 1.0f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-28 20:10:21 +00:00
|
|
|
void OscirenderLookAndFeel::drawComboBox(juce::Graphics& g, int width, int height, bool, int, int, int, int, juce::ComboBox& box) {
|
|
|
|
juce::Rectangle<int> boxBounds{0, 0, width, height};
|
|
|
|
|
2023-12-03 22:52:34 +00:00
|
|
|
g.setColour(box.findColour(juce::ComboBox::backgroundColourId));
|
2024-03-18 20:27:31 +00:00
|
|
|
g.fillRoundedRectangle(boxBounds.toFloat(), RECT_RADIUS);
|
2023-07-28 20:10:21 +00:00
|
|
|
|
|
|
|
juce::Rectangle<int> arrowZone{width - 15, 0, 10, height};
|
|
|
|
juce::Path path;
|
|
|
|
path.startNewSubPath((float)arrowZone.getX(), (float)arrowZone.getCentreY() - 3.0f);
|
|
|
|
path.lineTo((float)arrowZone.getCentreX(), (float)arrowZone.getCentreY() + 4.0f);
|
|
|
|
path.lineTo((float)arrowZone.getRight(), (float)arrowZone.getCentreY() - 3.0f);
|
|
|
|
path.closeSubPath();
|
|
|
|
|
2023-12-10 21:38:35 +00:00
|
|
|
g.setColour(box.findColour(juce::ComboBox::arrowColourId).withAlpha(box.isEnabled() ? 1.0f : 0.5f));
|
2023-07-28 20:10:21 +00:00
|
|
|
g.fillPath(path);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OscirenderLookAndFeel::positionComboBoxText(juce::ComboBox& box, juce::Label& label) {
|
2024-03-27 20:21:55 +00:00
|
|
|
label.setMouseCursor(juce::MouseCursor::PointingHandCursor);
|
2023-07-28 20:10:21 +00:00
|
|
|
label.setBounds(1, 1, box.getWidth() - 15, box.getHeight() - 2);
|
|
|
|
label.setFont(getComboBoxFont(box));
|
|
|
|
}
|
|
|
|
|
|
|
|
void OscirenderLookAndFeel::drawTickBox(juce::Graphics& g, juce::Component& component,
|
|
|
|
float x, float y, float w, float h,
|
|
|
|
const bool ticked,
|
|
|
|
const bool isEnabled,
|
|
|
|
const bool shouldDrawButtonAsHighlighted,
|
|
|
|
const bool shouldDrawButtonAsDown) {
|
|
|
|
juce::Rectangle<float> tickBounds(x, y, w, h);
|
|
|
|
|
|
|
|
g.setColour(component.findColour(juce::TextButton::buttonColourId));
|
2024-04-04 19:47:52 +00:00
|
|
|
g.fillRoundedRectangle(tickBounds, RECT_RADIUS);
|
2023-07-28 20:10:21 +00:00
|
|
|
|
|
|
|
if (ticked) {
|
|
|
|
g.setColour(component.findColour(juce::ToggleButton::tickColourId));
|
|
|
|
auto tick = getTickShape(0.75f);
|
|
|
|
g.fillPath(tick, tick.getTransformToScaleToFit(tickBounds.reduced(4, 5).toFloat(), false));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OscirenderLookAndFeel::drawGroupComponentOutline(juce::Graphics& g, int width, int height, const juce::String& text, const juce::Justification& position, juce::GroupComponent& group) {
|
|
|
|
auto bounds = group.getLocalBounds();
|
|
|
|
|
|
|
|
const float textH = 15.0f;
|
|
|
|
const float indent = 3.0f;
|
|
|
|
const float textEdgeGap = 4.0f;
|
|
|
|
auto cs = 5.0f;
|
|
|
|
|
|
|
|
juce::Font f(textH);
|
|
|
|
|
|
|
|
juce::Path p;
|
|
|
|
auto x = indent;
|
|
|
|
auto y = f.getAscent() - 3.0f;
|
|
|
|
auto w = juce::jmax(0.0f, (float)width - x * 2.0f);
|
|
|
|
auto h = juce::jmax(0.0f, (float)height - y - indent);
|
|
|
|
cs = juce::jmin(cs, w * 0.5f, h * 0.5f);
|
|
|
|
auto cs2 = 2.0f * cs;
|
|
|
|
|
|
|
|
auto textW = text.isEmpty() ? 0
|
|
|
|
: juce::jlimit(0.0f,
|
|
|
|
juce::jmax(0.0f, w - cs2 - textEdgeGap * 2),
|
|
|
|
(float)f.getStringWidth(text) + textEdgeGap * 2.0f);
|
|
|
|
auto textX = cs + textEdgeGap;
|
|
|
|
|
|
|
|
if (position.testFlags(juce::Justification::horizontallyCentred))
|
|
|
|
textX = cs + (w - cs2 - textW) * 0.5f;
|
|
|
|
else if (position.testFlags(juce::Justification::right))
|
|
|
|
textX = w - cs - textW - textEdgeGap;
|
|
|
|
|
|
|
|
auto alpha = group.isEnabled() ? 1.0f : 0.5f;
|
|
|
|
|
2024-03-18 20:27:31 +00:00
|
|
|
juce::Path background;
|
|
|
|
background.addRoundedRectangle(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight(), RECT_RADIUS, RECT_RADIUS);
|
2023-07-28 20:10:21 +00:00
|
|
|
g.setColour(group.findColour(groupComponentBackgroundColourId).withMultipliedAlpha(alpha));
|
2024-03-18 20:27:31 +00:00
|
|
|
g.fillPath(background);
|
2023-07-28 20:10:21 +00:00
|
|
|
|
|
|
|
auto header = bounds.removeFromTop(2 * textH);
|
|
|
|
|
2024-03-18 23:06:14 +00:00
|
|
|
juce::Path headerPath;
|
|
|
|
headerPath.addRoundedRectangle(header.getX(), header.getY(), header.getWidth(), header.getHeight(), RECT_RADIUS, RECT_RADIUS);
|
|
|
|
|
2023-07-28 20:10:21 +00:00
|
|
|
g.setColour(group.findColour(groupComponentHeaderColourId).withMultipliedAlpha(alpha));
|
2024-03-18 23:06:14 +00:00
|
|
|
g.fillPath(headerPath);
|
2023-07-28 20:10:21 +00:00
|
|
|
|
|
|
|
g.setColour(group.findColour(juce::GroupComponent::textColourId).withMultipliedAlpha(alpha));
|
|
|
|
g.setFont(f);
|
|
|
|
g.drawText(text,
|
|
|
|
juce::roundToInt(header.getX() + x + textX), header.getY() + 7,
|
|
|
|
juce::roundToInt(textW),
|
|
|
|
juce::roundToInt(textH),
|
|
|
|
juce::Justification::centred, true
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OscirenderLookAndFeel::drawLinearSlider(juce::Graphics& g, int x, int y, int width, int height, float sliderPos, float minSliderPos, float maxSliderPos, const juce::Slider::SliderStyle style, juce::Slider& slider) {
|
2023-12-03 22:52:34 +00:00
|
|
|
juce::LookAndFeel_V4::drawLinearSlider(g, x, y, width, height, sliderPos, minSliderPos, maxSliderPos, style, slider);
|
2023-12-03 22:37:38 +00:00
|
|
|
|
2023-07-28 20:10:21 +00:00
|
|
|
auto kx = slider.isHorizontal() ? sliderPos : ((float)x + (float)width * 0.5f);
|
|
|
|
auto ky = slider.isHorizontal() ? ((float)y + (float)height * 0.5f) : sliderPos;
|
|
|
|
|
|
|
|
juce::Point<float> point = { kx, ky };
|
|
|
|
|
|
|
|
auto thumbWidth = getSliderThumbRadius(slider);
|
|
|
|
|
2024-03-18 20:27:31 +00:00
|
|
|
juce::Path thumb;
|
|
|
|
thumb.addEllipse(juce::Rectangle<float>(static_cast<float>(thumbWidth), static_cast<float>(thumbWidth)).withCentre(point));
|
|
|
|
|
2023-12-10 21:38:35 +00:00
|
|
|
g.setColour(slider.findColour(sliderThumbOutlineColourId).withAlpha(slider.isEnabled() ? 1.0f : 0.5f));
|
2024-03-18 20:27:31 +00:00
|
|
|
g.strokePath(thumb, juce::PathStrokeType(1.0f));
|
2023-07-28 20:10:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void OscirenderLookAndFeel::drawButtonBackground(juce::Graphics& g, juce::Button& button, const juce::Colour& backgroundColour, bool shouldDrawButtonAsHighlighted, bool shouldDrawButtonAsDown) {
|
|
|
|
auto bounds = button.getLocalBounds().toFloat().reduced(0.5f, 0.5f);
|
|
|
|
|
2024-03-27 20:21:55 +00:00
|
|
|
auto baseColour = LookAndFeelHelpers::createBaseColour(backgroundColour, button.hasKeyboardFocus(true), shouldDrawButtonAsHighlighted, shouldDrawButtonAsDown, button.isEnabled());
|
2023-07-28 20:10:21 +00:00
|
|
|
|
|
|
|
g.setColour(baseColour);
|
2024-03-18 23:06:14 +00:00
|
|
|
g.fillRoundedRectangle(bounds, RECT_RADIUS);
|
2023-07-28 20:55:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void OscirenderLookAndFeel::drawMenuBarBackground(juce::Graphics& g, int width, int height, bool, juce::MenuBarComponent& menuBar) {
|
|
|
|
juce::Rectangle<int> r(width, height);
|
|
|
|
|
|
|
|
g.setColour(menuBar.findColour(juce::TextButton::buttonColourId));
|
|
|
|
g.fillRect(r);
|
2023-08-27 16:47:30 +00:00
|
|
|
}
|
|
|
|
|
2024-12-15 19:23:31 +00:00
|
|
|
juce::TextLayout OscirenderLookAndFeel::layoutTooltipText(const juce::String& text, juce::Colour colour) {
|
|
|
|
const float tooltipFontSize = 17.0f;
|
|
|
|
const int maxToolTipWidth = 600;
|
|
|
|
|
|
|
|
juce::AttributedString s;
|
|
|
|
s.setJustification (juce::Justification::centred);
|
|
|
|
s.append (text, juce::Font (tooltipFontSize, juce::Font::bold), colour);
|
|
|
|
|
|
|
|
juce::TextLayout tl;
|
|
|
|
tl.createLayoutWithBalancedLineLengths (s, (float) maxToolTipWidth);
|
|
|
|
return tl;
|
|
|
|
}
|
|
|
|
|
|
|
|
juce::Rectangle<int> OscirenderLookAndFeel::getTooltipBounds (const juce::String& tipText, juce::Point<int> screenPos, juce::Rectangle<int> parentArea) {
|
|
|
|
const juce::TextLayout tl (layoutTooltipText(tipText, juce::Colours::black));
|
|
|
|
|
|
|
|
auto w = (int) (tl.getWidth() + 14.0f);
|
|
|
|
auto h = (int) (tl.getHeight() + 6.0f);
|
|
|
|
|
|
|
|
return juce::Rectangle<int> (screenPos.x > parentArea.getCentreX() ? screenPos.x - (w + 12) : screenPos.x + 24,
|
|
|
|
screenPos.y > parentArea.getCentreY() ? screenPos.y - (h + 6) : screenPos.y + 6,
|
|
|
|
w, h)
|
|
|
|
.constrainedWithin (parentArea);
|
|
|
|
}
|
|
|
|
|
2023-12-17 21:32:56 +00:00
|
|
|
void OscirenderLookAndFeel::drawTooltip(juce::Graphics& g, const juce::String& text, int width, int height) {
|
|
|
|
juce::Rectangle<int> bounds (width, height);
|
|
|
|
|
|
|
|
g.setColour(findColour(juce::TooltipWindow::backgroundColourId));
|
2024-03-29 21:53:48 +00:00
|
|
|
g.fillRect(bounds);
|
2023-12-17 21:32:56 +00:00
|
|
|
|
2024-12-15 19:23:31 +00:00
|
|
|
layoutTooltipText(text, findColour(juce::TooltipWindow::textColourId))
|
|
|
|
.draw(g, {static_cast<float> (width), static_cast<float> (height)});
|
2023-12-17 21:32:56 +00:00
|
|
|
}
|
|
|
|
|
2024-03-29 22:37:27 +00:00
|
|
|
void OscirenderLookAndFeel::drawCornerResizer(juce::Graphics&, int w, int h, bool isMouseOver, bool isMouseDragging) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2024-04-04 19:47:52 +00:00
|
|
|
void OscirenderLookAndFeel::drawToggleButton (juce::Graphics& g, juce::ToggleButton& button, bool shouldDrawButtonAsHighlighted, bool shouldDrawButtonAsDown) {
|
|
|
|
LookAndFeel_V4::drawToggleButton(g, button, shouldDrawButtonAsHighlighted, shouldDrawButtonAsDown);
|
|
|
|
}
|
|
|
|
|
2023-08-27 16:47:30 +00:00
|
|
|
juce::CodeEditorComponent::ColourScheme OscirenderLookAndFeel::getDefaultColourScheme() {
|
|
|
|
juce::CodeEditorComponent::ColourScheme cs;
|
|
|
|
|
|
|
|
static const juce::CodeEditorComponent::ColourScheme::TokenType types[] = {
|
|
|
|
{"Error", juce::Colour(Dracula::red)},
|
|
|
|
{"Comment", juce::Colour(Dracula::comment)},
|
|
|
|
{"Keyword", juce::Colour(Dracula::pink)},
|
|
|
|
{"Operator", juce::Colour(Dracula::foreground)},
|
|
|
|
{"Identifier", juce::Colour(Dracula::foreground)},
|
|
|
|
{"Integer", juce::Colour(Dracula::purple)},
|
|
|
|
{"Float", juce::Colour(Dracula::purple)},
|
|
|
|
{"String", juce::Colour(Dracula::yellow)},
|
|
|
|
{"Bracket", juce::Colour(Dracula::foreground)},
|
|
|
|
{"Punctuation", juce::Colour(Dracula::pink)},
|
|
|
|
{"Preprocessor Text", juce::Colour(Dracula::comment)}
|
|
|
|
};
|
|
|
|
|
|
|
|
for (auto& t : types) {
|
|
|
|
cs.set(t.name, juce::Colour(t.colour));
|
|
|
|
}
|
|
|
|
|
|
|
|
return cs;
|
2024-03-27 20:21:55 +00:00
|
|
|
}
|
2024-05-25 18:45:15 +00:00
|
|
|
|
|
|
|
juce::MouseCursor OscirenderLookAndFeel::getMouseCursorFor(juce::Component& component) {
|
|
|
|
juce::Label* label = dynamic_cast<juce::Label*>(&component);
|
|
|
|
if (label != nullptr && label->isEditable()) {
|
|
|
|
return juce::MouseCursor::IBeamCursor;
|
|
|
|
}
|
|
|
|
juce::TextEditor* textEditor = dynamic_cast<juce::TextEditor*>(&component);
|
|
|
|
if (textEditor != nullptr) {
|
|
|
|
return juce::MouseCursor::IBeamCursor;
|
|
|
|
}
|
|
|
|
juce::Button* button = dynamic_cast<juce::Button*>(&component);
|
|
|
|
if (button != nullptr) {
|
|
|
|
return juce::MouseCursor::PointingHandCursor;
|
|
|
|
}
|
|
|
|
juce::ComboBox* comboBox = dynamic_cast<juce::ComboBox*>(&component);
|
|
|
|
if (comboBox != nullptr) {
|
|
|
|
return juce::MouseCursor::PointingHandCursor;
|
|
|
|
}
|
2024-06-02 18:32:02 +00:00
|
|
|
return juce::LookAndFeel_V4::getMouseCursorFor(component);
|
2024-05-25 18:45:15 +00:00
|
|
|
}
|
2024-08-13 18:19:05 +00:00
|
|
|
|
|
|
|
void OscirenderLookAndFeel::drawCallOutBoxBackground(juce::CallOutBox& box, juce::Graphics& g, const juce::Path& path, juce::Image& cachedImage) {
|
|
|
|
if (cachedImage.isNull()) {
|
|
|
|
cachedImage = juce::Image(juce::Image::ARGB, box.getWidth(), box.getHeight(), true);
|
|
|
|
juce::Graphics g2(cachedImage);
|
|
|
|
|
|
|
|
juce::DropShadow(juce::Colours::black.withAlpha(0.7f), 8, juce::Point<int>(0, 2)).drawForPath(g2, path);
|
|
|
|
}
|
|
|
|
|
|
|
|
g.setColour(juce::Colours::black);
|
|
|
|
g.drawImageAt(cachedImage, 0, 0);
|
|
|
|
|
|
|
|
g.setColour(Colours::dark);
|
|
|
|
g.fillPath(path);
|
|
|
|
|
|
|
|
g.setColour(juce::Colours::black);
|
|
|
|
g.strokePath(path, juce::PathStrokeType(1.0f));
|
|
|
|
}
|
2024-11-30 21:11:49 +00:00
|
|
|
|
|
|
|
void OscirenderLookAndFeel::drawProgressBar(juce::Graphics& g, juce::ProgressBar& progressBar, int width, int height, double progress, const juce::String& textToShow) {
|
|
|
|
switch (progressBar.getResolvedStyle()) {
|
|
|
|
case juce::ProgressBar::Style::linear:
|
|
|
|
customDrawLinearProgressBar(g, progressBar, width, height, progress, textToShow);
|
|
|
|
break;
|
|
|
|
case juce::ProgressBar::Style::circular:
|
|
|
|
juce::LookAndFeel_V4::drawProgressBar(g, progressBar, width, height, progress, textToShow);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OscirenderLookAndFeel::customDrawLinearProgressBar(juce::Graphics& g, const juce::ProgressBar& progressBar, int width, int height, double progress, const juce::String& textToShow) {
|
|
|
|
auto background = progressBar.findColour(juce::ProgressBar::backgroundColourId);
|
|
|
|
auto foreground = progressBar.findColour(juce::ProgressBar::foregroundColourId).withAlpha(0.5f);
|
|
|
|
int rectRadius = 2;
|
|
|
|
|
|
|
|
auto barBounds = progressBar.getLocalBounds().toFloat();
|
|
|
|
|
|
|
|
g.setColour(background);
|
|
|
|
g.fillRoundedRectangle(barBounds, rectRadius);
|
|
|
|
|
|
|
|
juce::String text = textToShow.isEmpty() ? "waiting..." : textToShow;
|
|
|
|
|
|
|
|
if (progress >= 0.0f && progress <= 1.0f) {
|
|
|
|
juce::Path p;
|
|
|
|
p.addRoundedRectangle(barBounds, rectRadius);
|
|
|
|
g.reduceClipRegion(p);
|
|
|
|
|
|
|
|
barBounds.setWidth(barBounds.getWidth() * (float) progress);
|
|
|
|
g.setColour(foreground);
|
|
|
|
g.fillRoundedRectangle(barBounds, rectRadius);
|
|
|
|
} else {
|
|
|
|
if (progress == -2) {
|
|
|
|
background = juce::Colours::red;
|
|
|
|
text = "Error";
|
|
|
|
}
|
|
|
|
|
|
|
|
// spinning bar..
|
|
|
|
g.setColour(background);
|
|
|
|
|
|
|
|
auto stripeWidth = height * 2;
|
|
|
|
auto position = static_cast<int>(juce::Time::getMillisecondCounter() / 15) % stripeWidth;
|
|
|
|
|
|
|
|
juce::Path p;
|
|
|
|
|
|
|
|
for (auto x = static_cast<float> (-position); x < (float) (width + stripeWidth); x += (float) stripeWidth) {
|
|
|
|
p.addQuadrilateral (x, 0.0f,
|
|
|
|
x + (float) stripeWidth * 0.5f, 0.0f,
|
|
|
|
x, static_cast<float> (height),
|
|
|
|
x - (float) stripeWidth * 0.5f, static_cast<float> (height));
|
|
|
|
}
|
|
|
|
|
|
|
|
juce::Image im(juce::Image::ARGB, width, height, true);
|
|
|
|
|
|
|
|
{
|
|
|
|
juce::Graphics g2(im);
|
|
|
|
g2.setColour(foreground);
|
|
|
|
g2.fillRoundedRectangle(barBounds, rectRadius);
|
|
|
|
}
|
|
|
|
|
|
|
|
g.setTiledImageFill(im, 0, 0, 0.85f);
|
|
|
|
g.fillPath(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
g.setColour(juce::Colours::white);
|
|
|
|
juce::Font font = juce::Font(juce::FontOptions((float) height * 0.9f, juce::Font::bold));
|
|
|
|
g.setFont(font);
|
|
|
|
|
|
|
|
g.drawText(text, 0, 0, width, height, juce::Justification::centred, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
juce::Typeface::Ptr OscirenderLookAndFeel::getTypefaceForFont(const juce::Font& font) {
|
|
|
|
if (font.getTypefaceName() == juce::Font::getDefaultSansSerifFontName()) {
|
|
|
|
if (font.getTypefaceStyle() == "Regular") {
|
|
|
|
return regularTypeface;
|
|
|
|
} else if (font.getTypefaceStyle() == "Bold") {
|
|
|
|
return boldTypeface;
|
|
|
|
} else if (font.getTypefaceStyle() == "Italic") {
|
|
|
|
return italicTypeface;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return juce::Font::getDefaultTypefaceForFont(font);
|
|
|
|
}
|