diff --git a/resources/customComponents/AnimatedLabel.h b/resources/customComponents/AnimatedLabel.h new file mode 100644 index 0000000..9ba46ad --- /dev/null +++ b/resources/customComponents/AnimatedLabel.h @@ -0,0 +1,190 @@ +/* + ============================================================================== + + AnimatedLabel.h + Created: 23 Jun 2023 10:32:56am + Author: mikol + + ============================================================================== +*/ + +#pragma once + +#include +#include "../resources/lookAndFeel/MainLookAndFeel.h" +//============================================================================== +/* +*/ +class AnimatedLabel : public juce::Component, + private juce::Timer +{ +public: + AnimatedLabel() + { + it = 0; + counter = 1; + fontHeight = 14.f; + repaintBypassed = false; + timerBypassedPeriods = 0; + addAndMakeVisible(&animatedRectangle); + animatedRectangle.setVisible(false); + } + + ~AnimatedLabel() override + { + } + + void startAnimation(const String primText, const String secText = {}) + { + it = 0; + counter = 1; + fontHeight = 14.f; + repaintBypassed = false; + timerBypassedPeriods = 0; + animatedString.clear(); + startTimer(100); + setLabelText(primText, secText); + animatedRectangle.setVisible(true); + } + + void stopAnimation() + { + it = 0; + counter = 1; + fontHeight = 14.f; + repaintBypassed = false; + timerBypassedPeriods = 0; + animatedString.clear(); + stopTimer(); + animatedRectangle.setVisible(false); + } + + void paint (juce::Graphics& g) override + { + fontHeight = getTopLevelComponent()->getHeight() * 0.018f; + textArea = getLocalBounds().reduced(getLocalBounds().getWidth() * 0.06f, (getLocalBounds().getHeight() - fontHeight)/2); + g.fillAll (mainLaF.labelBackgroundColor); + + g.setColour (mainLaF.mainTextColor); + g.setFont (fontHeight); + + g.drawMultiLineText(animatedString, textArea.getX(), textArea.getY() + fontHeight/2, textArea.getWidth(), + juce::Justification::left, true); + } + + void resized() override + { + fontHeight = getTopLevelComponent()->getHeight() * 0.018f; + + Font font(fontHeight); + textArea = getLocalBounds().reduced(getLocalBounds().getWidth() * 0.06f, (getLocalBounds().getHeight() - fontHeight) / 2); + auto centredTextArea = Rectangle(textArea.getX(), textArea.getY() - fontHeight/4, textArea.getWidth(), fontHeight); + int equalSignWidth = getLocalBounds().getWidth() * 0.042f; + float rowProportion = static_cast(font.getStringWidth(animatedString)) / static_cast(centredTextArea.getWidth()); + + if (animatedString.length() > 0) + { + auto currStringLength = animatedString.length(); + equalSignWidth = font.getStringWidth(animatedString) / animatedString.length(); + if (font.getStringWidth(animatedString) > centredTextArea.getWidth()) + { + int nrOfSignsInNewRow = (rowProportion - 1.f) * (centredTextArea.getWidth()/ equalSignWidth); + rectArea = centredTextArea.withWidth(equalSignWidth).translated(equalSignWidth * nrOfSignsInNewRow, fontHeight); + } + else + { + rectArea = centredTextArea.withWidth(equalSignWidth).translated(equalSignWidth * currStringLength, 0); + } + } + else + { + rectArea = centredTextArea.withWidth(equalSignWidth); + } + animatedRectangle.setBounds(rectArea); + } + +private: + String animatedString; + int it; + int fontHeight; + Font textFont; + int timerBypassedPeriods; + bool repaintBypassed; + String text; + String primaryText; + String secondaryText; + int counter; + + void setLabelText(const String primText, const String secText = {}) + { + primaryText = primText; + secondaryText = secText; + text = primaryText; + } + + void timerCallback() override + { + auto charStr = text.getCharPointer(); + + if (!repaintBypassed && it < text.length()) + { + animatedString += charStr[it]; + it++; + repaint(); + } + else + { + it = 0; + repaintBypassed = true; + timerBypassedPeriods++; + if (timerBypassedPeriods > 30) + { + counter++; + repaintBypassed = false; + text = (!secondaryText.isEmpty() && counter % 2 == 0) ? secondaryText : primaryText; + timerBypassedPeriods = 0; + animatedString.clear(); + } + } + resized(); + } + + class AnimatedRectangle : public juce::Component, + private juce::Timer + { + public: + AnimatedRectangle() + { + startTimer(300); + } + + ~AnimatedRectangle() override + { + } + + void paint(juce::Graphics& g) override + { + if (show) + g.fillAll(mainLaF.mainTextColor); + } + + void resized() override + { + } + + private: + bool show = false; + void timerCallback() override + { + show = !show; + repaint(); + } + MainLookAndFeel mainLaF; + } animatedRectangle; + + Rectangle textArea; + Rectangle rectArea; + MainLookAndFeel mainLaF; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AnimatedLabel) +}; diff --git a/resources/customComponents/DirectivityEQ.h b/resources/customComponents/DirectivityEQ.h index 500c95a..1015383 100644 --- a/resources/customComponents/DirectivityEQ.h +++ b/resources/customComponents/DirectivityEQ.h @@ -47,27 +47,11 @@ ============================================================================== */ - #pragma once -#include "ImgPaths.h" - -// !J! On iOS we make the knobs fatter for touchscreen ease-of-use -#ifdef JUCE_IOS -static const float POLAR_DESIGNER_KNOBS_SIZE = 40.0f; -static const float POLAR_DESIGNER_BANDLIMIT_DIVIDER_SIZE = 8.0f; -#else -static const float POLAR_DESIGNER_KNOBS_SIZE = 20.0f; -static const float POLAR_DESIGNER_BANDLIMIT_DIVIDER_SIZE = 4.0f; -#endif - -class DirectivityEQ : public Component, private Slider::Listener, private Label::Listener -{ +#include "../resources/lookAndFeel/MainLookAndFeel.h" -#ifdef AA_DO_DEBUG_PATH -#warning "AUSTRIANAUDIO: DEBUG PATHS ARE TURNED ON!" - Path debugPath; // !J! used for the purpose of debugging UI elements only -#endif - +class DirectivityEQ : public Component, private Slider::Listener, private Label::Listener, private Button::Listener +{ struct Settings { float fMin = 20.0f; // minimum displayed frequency float fMax = 20000.0f; // maximum displayed frequency @@ -80,8 +64,8 @@ class DirectivityEQ : public Component, private Slider::Listener, private Label Slider* dirSlider = nullptr; Slider* lowerFrequencySlider = nullptr; Slider* upperFrequencySlider = nullptr; - MuteSoloButton* soloButton = nullptr; - MuteSoloButton* muteButton = nullptr; + ToggleButton* soloButton = nullptr; + ToggleButton* muteButton = nullptr; Colour colour; Slider* gainSlider = nullptr; PolarPatternVisualizer* polarPatternVisualizer = nullptr; @@ -90,12 +74,13 @@ class DirectivityEQ : public Component, private Slider::Listener, private Label }; // margins - const float mL = 33.0f; - const float mR = 10.0f; - const float mT = 15.0f; - const float mB = 15.0f; + float mL = 43.0f; + const float mR = 15.0f; + float mT = 33.0f; + float mB = 20.0f; const float OH = 3.0f; - + float mLabel = 5.0f; + class PathComponent : public Component { public: @@ -105,14 +90,46 @@ class DirectivityEQ : public Component, private Slider::Listener, private Label path.preallocateSpace(1000); // !J! Arbitrary Magic Number }; ~PathComponent() {}; - - void setBounds() { Component::setBounds ( path.getBounds().withWidth(10.0f).translated(-3.0f,0.0f).toNearestInt()); } - + void setBounds() + { + int deltaX = 0; + + if (SystemStats::getOperatingSystemName() == "iOS") + deltaX = path.getBounds().getWidth() * 2; + + Component::setBounds(path.getBounds().toNearestInt().expanded(deltaX, 0)); + } Path& getPath() { return path; } private: Path path; }; - + + class BandLimitDividerHolder : public Component + { + public: + BandLimitDividerHolder() : Component() { + setAlwaysOnTop(true); + setName("PathComponent"); + path.preallocateSpace(1000); + }; + ~BandLimitDividerHolder() {}; + void setBounds() + { + int deltaX = 0; + int deltaY = 0; + if (SystemStats::getOperatingSystemName() == "iOS") + { + deltaX = path.getBounds().getWidth(); + deltaY = path.getBounds().getHeight(); + } + + Component::setBounds(path.getBounds().toNearestInt().expanded(deltaX, deltaY)); + } + Path& getPath(){ return path; } + private: + Path path; + }; + class RectangleComponent : public Component { public: @@ -121,47 +138,121 @@ class DirectivityEQ : public Component, private Slider::Listener, private Label setName("RectangleComponent"); }; ~RectangleComponent() {}; - + void setBounds(float x, float y, float width, float height) { rectangle.setBounds (x, y, width, height); Component::setBounds (rectangle.toNearestInt()); } - private: Rectangle rectangle; }; + class BandKnobComponent : public Component + { + public: + BandKnobComponent() : Component() { + setAlwaysOnTop(true); + setName("BandKnobComponent"); + }; + ~BandKnobComponent() {}; + void paint(Graphics& g) override + { + int circX = getLocalBounds().getCentreX(); + int circY = getLocalBounds().getCentreY(); + int circleSize = getLocalBounds().getWidth(); + bool resultMainImg; + + auto bandHandleKnobImg = juce::Drawable::createFromImageData(BinaryData::bandHandleKnob_svg, BinaryData::bandHandleKnob_svgSize); + bandHandleKnobImageArea = Rectangle(circX - (circleSize / 2), circY - (circleSize / 2), circleSize, circleSize); + + if(SystemStats::getOperatingSystemName() == "iOS") + bandHandleKnobImageArea.reduce(proportionOfHeight(0.23f), proportionOfHeight(0.23f)); + + + if (!isEnabled()) + { + resultMainImg = bandHandleKnobImg->replaceColour(Colours::white, Colours::black); + } + else + { + resultMainImg = bandHandleKnobImg->replaceColour(Colours::black, Colours::white); + } + bandHandleKnobImg->drawWithin(g, bandHandleKnobImageArea, juce::RectanglePlacement::centred, 1.f); + } + + void setBounds(float x, float y, float width, float height) + { + rectangle.setBounds(x, y, width, height); + Component::setBounds(rectangle.toNearestInt()); + } + + bool hitTest(int x, int y) override + { + Path knobArea; + if (SystemStats::getOperatingSystemName() == "iOS") + knobArea.addRectangle(getLocalBounds()); + else + knobArea.addEllipse(bandHandleKnobImageArea); + + return knobArea.contains(x, y); + } + private: + Rectangle rectangle; + Rectangle bandHandleKnobImageArea; + }; + public: DirectivityEQ(PolarDesignerAudioProcessor& p) : Component(), processor(p), nrActiveBands(0), soloActive(false), dirFactArray{omniFact, cardFact, rCardFact, eightFact, bCardFact, rbCardFact, sCardFact, hCardFact} { - cardPath.loadPathFromData (cardData, sizeof (cardData)); - eightPath.loadPathFromData (eightData, sizeof (eightData)); - omniPath.loadPathFromData (omniData, sizeof (omniData)); - rCardPath.loadPathFromData (cardData, sizeof (cardData)); - rCardPath.applyTransform (AffineTransform::rotation(M_PI)); - sCardPath.loadPathFromData (sCardData, sizeof (sCardData)); - hCardPath.loadPathFromData (hCardData, sizeof (hCardData)); - bCardPath.loadPathFromData (bCardData, sizeof (bCardData)); - rbCardPath.loadPathFromData (bCardData, sizeof (bCardData)); - rbCardPath.applyTransform (AffineTransform::rotation(M_PI)); + setLookAndFeel(&mainLaF); + + addAndMakeVisible(&tbPrimDirButtons[0]); + tbPrimDirButtons[0].setButtonText("Eight Pattern"); + tbPrimDirButtons[0].addListener(this); + addAndMakeVisible(&tbPrimDirButtons[1]); + tbPrimDirButtons[1].setButtonText("Cardioid Pattern"); + tbPrimDirButtons[1].addListener(this); + addAndMakeVisible(&tbPrimDirButtons[2]); + tbPrimDirButtons[2].setButtonText("Omni Pattern"); + tbPrimDirButtons[2].addListener(this); + addAndMakeVisible(&tbPrimDirButtons[3]); + tbPrimDirButtons[3].setButtonText("RevCardioid Pattern"); + tbPrimDirButtons[3].addListener(this); + + addAndMakeVisible(&tbSecDirButtons[0]); + tbSecDirButtons[0].setButtonText("HyperCardioid Pattern"); + tbSecDirButtons[0].addListener(this); + addAndMakeVisible(&tbSecDirButtons[1]); + tbSecDirButtons[1].setButtonText("SuperCardioid Pattern"); + tbSecDirButtons[1].addListener(this); + addAndMakeVisible(&tbSecDirButtons[2]); + tbSecDirButtons[2].setButtonText("BCardioid Pattern"); + tbSecDirButtons[2].addListener(this); + addAndMakeVisible(&tbSecDirButtons[3]); + tbSecDirButtons[3].setButtonText("RevBCardioid Pattern"); + tbSecDirButtons[3].addListener(this); + init(); - + for (int i = 0; i < 4; ++i) { addAndMakeVisible (&bandLimitPaths[i]); bandLimitPaths[i].addMouseListener(this, true); + addAndMakeVisible(&bandLimitDividerHolders[i]); + bandLimitDividerHolders[i].addMouseListener(this, true); } - + for (int i = 0; i < 5; ++i) { addAndMakeVisible (&dirPathRects[i]); dirPathRects[i].addMouseListener(this, true); + addAndMakeVisible(&bandKnobs[i]); + bandKnobs[i].addMouseListener(this, true); } - }; void init () @@ -171,76 +262,53 @@ class DirectivityEQ : public Component, private Slider::Listener, private Label } ~DirectivityEQ() { + setLookAndFeel(nullptr); }; void paint (Graphics& g) override { nrActiveBands = processor.getNBands(); - + if (processor.zeroDelayModeActive()) nrActiveBands = 1; - + // make sure visibility of paths for grabbing is on for active bands and if no mouse dragging occurs if (nrActiveBands != oldNrActiveBands && activeElem == -1) { for (int i = 0; i < 5; ++i) { if (i < nrActiveBands) + { dirPathRects[i].setVisible(true); + bandKnobs[i].setVisible(true); + } else + { dirPathRects[i].setVisible(false); + bandKnobs[i].setVisible(false); + } } for (int i = 0; i < 4; ++i) { if (i < nrActiveBands - 1) + { bandLimitPaths[i].setVisible(true); + bandLimitDividerHolders[i].setVisible(true); + } else + { bandLimitPaths[i].setVisible(false); + bandLimitDividerHolders[i].setVisible(false); + } } } - - // directivity labels - int height = getHeight(); - int dirImgSize = 20; - int smallImgSize = 15; - float strokeSizeThin = 0.5f; - float strokeSizeThick = 2.0f; - eightPath.applyTransform (eightPath.getTransformToScaleToFit (5.0f, mT - dirImgSize / 2, dirImgSize, dirImgSize, true, Justification::left)); - g.setColour (Colours::white); - g.strokePath (eightPath, PathStrokeType (activePatternPath == eightFact ? strokeSizeThick : strokeSizeThin)); - g.fillPath (eightPath); - - hCardPath.applyTransform (hCardPath.getTransformToScaleToFit (mL / 2 - 15.0f, static_cast(height) / 6 + 3.0f, smallImgSize, smallImgSize, true, Justification::right)); - g.strokePath (hCardPath, PathStrokeType (activePatternPath == hCardFact ? strokeSizeThick : strokeSizeThin)); - g.fillPath (hCardPath); - - sCardPath.applyTransform (sCardPath.getTransformToScaleToFit (mL / 2 - 14.0f, static_cast(height) / 4, smallImgSize, smallImgSize, true, Justification::right)); - g.strokePath (sCardPath, PathStrokeType (activePatternPath == sCardFact ? strokeSizeThick : strokeSizeThin)); - g.fillPath (sCardPath); - - cardPath.applyTransform (cardPath.getTransformToScaleToFit (1.0f, static_cast(height) / 3 - dirImgSize / 2 + 4.0f, dirImgSize, dirImgSize, true, Justification::right)); - g.strokePath (cardPath, PathStrokeType (activePatternPath == cardFact ? strokeSizeThick : strokeSizeThin)); - g.fillPath (cardPath); - - bCardPath.applyTransform (bCardPath.getTransformToScaleToFit (mL / 2 - 13.0f, static_cast(height) / 2 - 27.0f, smallImgSize, smallImgSize, true, Justification::right)); - g.strokePath (bCardPath, PathStrokeType (activePatternPath == bCardFact ? strokeSizeThick : strokeSizeThin)); - g.fillPath (bCardPath); - - omniPath.applyTransform (omniPath.getTransformToScaleToFit (1.0f, static_cast(height) * 2 / 3 - dirImgSize / 2 - 6.0f, dirImgSize, dirImgSize, true, Justification::right)); - g.strokePath (omniPath, PathStrokeType (activePatternPath == omniFact ? strokeSizeThick : strokeSizeThin)); - g.fillPath (omniPath); - - rbCardPath.applyTransform (rbCardPath.getTransformToScaleToFit (mL / 2 - 13.0f, static_cast(height) - mB - smallImgSize / 2 - 22.0f, smallImgSize, smallImgSize, true, Justification::right)); - g.strokePath (rbCardPath, PathStrokeType (activePatternPath == rbCardFact ? strokeSizeThick : strokeSizeThin)); - g.fillPath (rbCardPath); - - rCardPath.applyTransform (rCardPath.getTransformToScaleToFit (1.0f, static_cast(height) - mB - dirImgSize / 2, dirImgSize, dirImgSize, true, Justification::right)); - g.strokePath (rCardPath, PathStrokeType (activePatternPath == rCardFact ? strokeSizeThick : strokeSizeThin)); - g.fillPath (rCardPath); - + // frequency labels - g.setFont (getLookAndFeel().getTypefaceForFont (Font(12.0f, 2))); - g.setFont (16.0f); + Font axisLabelFont = getLookAndFeel().getTypefaceForFont(Font(12.0f, 1)); + g.setFont (axisLabelFont); + g.setFont (proportionOfHeight(0.05f)); + g.setColour(mainLaF.mainTextColor); + mLabel = proportionOfHeight(0.02f); for (float f=s.fMin; f <= s.fMax; f += powf(10, floorf(log10(f)))) { int xpos = hzToX(f); @@ -262,94 +330,105 @@ class DirectivityEQ : public Component, private Slider::Listener, private Label if (drawText) { - g.drawText (axislabel, xpos - 10, dirToY(s.yMin) + OH + 0.0f, 30, 12, Justification::centred, true); + auto justification = Justification::centred; + auto x = xpos - axisLabelFont.getStringWidth(axislabel) / 2 - mLabel; + auto y = dirToY(s.yMin) + OH + mLabel; + auto width = axisLabelFont.getStringWidth(axislabel) + 2 * mLabel; + auto height = axisLabelFont.getHeight(); + if (axislabel == "20k" && ((x + width) > getWidth())) + { + justification = Justification::right; + x = getWidth() - width; + } + g.drawText(axislabel, x, y, width, height, justification, true); } } - g.setColour (Colours::whitesmoke.withMultipliedAlpha(0.1f)); + g.setColour (Colours::white.withAlpha(0.05f)); g.fillRect (static_cast(hzToX(s.fMin)), dirToY(0), static_cast(hzToX(s.fMax) - hzToX(s.fMin)), dirToY(-0.5) - dirToY(0)); - + // set path colours and stroke - g.setColour (Colours::white); - g.strokePath (dirGridPath, PathStrokeType (0.5f)); + g.setColour (mainLaF.mainTextInactiveColor); + g.strokePath (dirGridPath, PathStrokeType (0.25f)); - g.setColour (Colours::white.withMultipliedAlpha(0.5f)); - g.strokePath (smallDirGridPath, PathStrokeType (0.5f)); + g.setColour(mainLaF.mainTextInactiveColor); + g.strokePath (smallDirGridPath, PathStrokeType (0.25f)); - g.setColour (Colours::white); - g.strokePath (hzGridPathBold, PathStrokeType (0.5f)); + g.setColour(mainLaF.mainTextInactiveColor); + g.strokePath (hzGridPathBold, PathStrokeType (0.25f)); - g.setColour (Colours::white.withMultipliedAlpha(0.5f)); - g.strokePath (hzGridPath, PathStrokeType (0.5f)); + g.setColour(mainLaF.mainTextInactiveColor); + g.strokePath (hzGridPath, PathStrokeType (0.25f)); for (PathComponent& p : bandLimitPaths) { p.getPath().clear(); } + for (BandLimitDividerHolder& p : bandLimitDividerHolders) + { + p.getPath().clear(); + } for (Path& p : dirPaths) { p.clear(); } - -#ifdef AA_DO_DEBUG_PATH - debugPath.clear(); // !J! Used only for debugging UI elements -#endif - float lastRightBound; float lastCircY; int bandMargin = 20; int interpPointMargin = 15; int patternRectHeight = 14; - + int bandLimitDividerWidth = proportionOfWidth(0.005f); + int bandLimitDividerHolderY = mT / 2; + int bandLimitDividerHolderWidth = proportionOfWidth(0.017f); + int bandLimitDividerHolderHeight = dirToY(s.yMax) - 2.f;; + int bandLineThickness = proportionOfHeight(0.006f); + // paint dirPaths and bandLimitPaths for (int i = 0; i < nrActiveBands; ++i) { BandElements& handle(elements.getReference(i)); - + float rightBound = (handle.upperFrequencySlider == nullptr || nrActiveBands == i + 1) ? hzToX(s.fMax) : hzToX (processor.hzFromZeroToOne(i, handle.upperFrequencySlider->getValue())); - + float circY = handle.dirSlider == nullptr ? dirToY(0.0f) : dirToY(handle.dirSlider->getValue()); - + // paint band limits if (i != nrActiveBands - 1) { Path& blPath = bandLimitPaths[i].getPath(); - - blPath.startNewSubPath (rightBound, dirToY(s.yMax)-OH); - - blPath.lineTo (rightBound, dirToY(s.yMin)+OH); - -//blPath.addRectangle(rightBound - 20.0, dirToY(s.yMin)+OH - 20, 40, 40); - - g.setColour (Colours::steelblue.withMultipliedAlpha(activeBandLimitPath == i ? 1.0f : 0.8f)); + bandsWidth[i] = bandLimitPaths[i].getX() - mL + bandLimitDividerWidth/2; + blPath.addRectangle(rightBound - bandLimitDividerWidth/2, dirToY(s.yMax), bandLimitDividerWidth, dirToY(s.yMin) - mT); - g.strokePath (blPath, PathStrokeType (POLAR_DESIGNER_BANDLIMIT_DIVIDER_SIZE)); + g.setColour (mainLaF.textButtonFrameColor.withMultipliedAlpha(activeBandLimitPath == i ? 1.0f : 0.8f)); + g.fillPath(blPath); -#ifdef AA_DO_DEBUG_PATH - { // !J! for debug purposes only - - debugPath.startNewSubPath(bandLimitPaths[i].getBounds().getX(), - bandLimitPaths[i].getBounds().getY()); + bandLimitPaths[i].setBounds(); - debugPath.lineTo(bandLimitPaths[i].getBounds().getRight(), - bandLimitPaths[i].getBounds().getBottom()); + Path& blDhPath = bandLimitDividerHolders[i].getPath(); - debugPath.addRectangle(bandLimitPaths[i].getBounds().getX(), bandLimitPaths[i].getBounds().getY(), - bandLimitPaths[i].getBounds().getWidth(), bandLimitPaths[i].getBounds().getHeight()); + Point point1(rightBound - bandLimitDividerHolderWidth / 2, bandLimitDividerHolderY); + Point point2(rightBound + bandLimitDividerHolderWidth / 2, bandLimitDividerHolderY); + Point point3(rightBound + bandLimitDividerHolderWidth / 2, bandLimitDividerHolderHeight * 0.88f); + Point point4(rightBound, bandLimitDividerHolderHeight); + Point point5(rightBound - bandLimitDividerHolderWidth / 2, bandLimitDividerHolderHeight * 0.88f); -// debugPath.addStar(bandLimitPaths[i].getScreenPosition().toFloat(), 8, 10, 20); - } -#endif - - bandLimitPaths[i].setBounds(); + blDhPath.startNewSubPath(point1); + blDhPath.lineTo(point2); + blDhPath.lineTo(point3); + blDhPath.lineTo(point4); + blDhPath.lineTo(point5); + blDhPath.closeSubPath(); + g.setColour(mainLaF.textButtonFrameColor.withMultipliedAlpha(activeBandLimitPath == i ? 1.0f : 0.8f)); + g.fillPath(blDhPath); + bandLimitDividerHolders[i].setBounds(); } - + // dirPath if (nrActiveBands == 1) { @@ -358,11 +437,11 @@ class DirectivityEQ : public Component, private Slider::Listener, private Label dirPaths[i].startNewSubPath (hzToX(s.fMin), circY); dirPaths[i].lineTo (hzToX(s.fMax), circY); - g.setColour (handle.colour.withSaturation(activeElem == i ? 0.6 : 0.5f).withMultipliedAlpha(calcAlphaOfDirPath(handle))); - g.strokePath (dirPaths[i], PathStrokeType (3.0f)); + g.setColour(dirPathRects[i].isEnabled() ? handle.colour : handle.colour.withBrightness(0.3f)); + g.strokePath (dirPaths[i], PathStrokeType (bandLineThickness)); break; } - + if (i == 0) { // set surrounding rectangle to trigger mouse drag and for aax automation shortcut @@ -375,30 +454,28 @@ class DirectivityEQ : public Component, private Slider::Listener, private Label { // set surrounding rectangle to trigger mouse drag and for aax automation shortcut dirPathRects[i].setBounds(lastRightBound + bandMargin, circY - patternRectHeight/2, hzToX(s.fMax) - lastRightBound - bandMargin, patternRectHeight); - + dirPaths[i-1].startNewSubPath (lastRightBound - bandMargin, lastCircY); dirPaths[i-1].quadraticTo (lastRightBound - bandMargin + interpPointMargin, lastCircY, lastRightBound, (lastCircY + circY) / 2); - g.setColour (elements.getReference(i-1).colour.withSaturation(activeElem == i-1 ? 0.6 : 0.5f). - withMultipliedAlpha(calcAlphaOfDirPath(elements.getReference(i-1)))); - g.strokePath (dirPaths[i-1], PathStrokeType (3.0f)); - + g.setColour(dirPathRects[i-1].isEnabled() ? elements.getReference(i-1).colour : elements.getReference(i - 1).colour.withBrightness(0.3f)); + g.strokePath (dirPaths[i-1], PathStrokeType (bandLineThickness)); + dirPaths[i].startNewSubPath (lastRightBound, (lastCircY + circY) / 2); dirPaths[i].quadraticTo (lastRightBound + bandMargin - interpPointMargin, circY, lastRightBound + bandMargin, circY); dirPaths[i].lineTo (hzToX(s.fMax), circY); - g.setColour (handle.colour.withSaturation(activeElem == i ? 0.6 : 0.5f).withMultipliedAlpha(calcAlphaOfDirPath(handle))); - g.strokePath (dirPaths[i], PathStrokeType (3.0f)); + g.setColour(dirPathRects[i].isEnabled() ? handle.colour : handle.colour.withBrightness(0.3f)); + g.strokePath (dirPaths[i], PathStrokeType (bandLineThickness)); } else { // set surrounding rectangle to trigger mouse drag and for aax automation shortcut dirPathRects[i].setBounds(lastRightBound + bandMargin, circY - patternRectHeight/2, rightBound - bandMargin - lastRightBound - bandMargin, patternRectHeight); - + dirPaths[i-1].startNewSubPath (lastRightBound - bandMargin, lastCircY); dirPaths[i-1].quadraticTo (lastRightBound - bandMargin + interpPointMargin, lastCircY, lastRightBound, (lastCircY + circY) / 2); - g.setColour (elements.getReference(i-1).colour.withSaturation(activeElem == i-1 ? 0.6 : 0.5f). - withMultipliedAlpha(calcAlphaOfDirPath(elements.getReference(i-1)))); - g.strokePath (dirPaths[i-1], PathStrokeType (3.0f)); - + g.setColour(dirPathRects[i-1].isEnabled() ? elements.getReference(i - 1).colour : elements.getReference(i - 1).colour.withBrightness(0.3f)); + g.strokePath (dirPaths[i-1], PathStrokeType (bandLineThickness)); + dirPaths[i].startNewSubPath (lastRightBound, (lastCircY + circY) / 2); dirPaths[i].quadraticTo (lastRightBound + bandMargin - interpPointMargin, circY, lastRightBound + bandMargin, circY); dirPaths[i].lineTo (rightBound - bandMargin, circY); @@ -407,8 +484,12 @@ class DirectivityEQ : public Component, private Slider::Listener, private Label lastCircY = circY; } - // band handle knobs + int knobSize = proportionOfHeight(0.075f); + + if (SystemStats::getOperatingSystemName() == "iOS") + knobSize = proportionOfHeight(0.145f); + for (int i = 0; i < nrActiveBands; ++i) { BandElements& handle (elements.getReference(i)); @@ -417,91 +498,39 @@ class DirectivityEQ : public Component, private Slider::Listener, private Label float circX = (rightBound + leftBound) / 2; float circY = handle.dirSlider == nullptr ? dirToY (0.0f) : dirToY (handle.dirSlider->getValue()); handle.handlePos.setXY(circX,circY); - - // paint band handles - g.setColour (Colour (0xFF191919)); - - g.drawEllipse (circX - (POLAR_DESIGNER_KNOBS_SIZE / 2), - circY - (POLAR_DESIGNER_KNOBS_SIZE / 2) , - POLAR_DESIGNER_KNOBS_SIZE, - POLAR_DESIGNER_KNOBS_SIZE, 3.0f); - - g.setColour (handle.colour); - - g.drawEllipse (circX - (POLAR_DESIGNER_KNOBS_SIZE / 2), - circY - (POLAR_DESIGNER_KNOBS_SIZE / 2), - POLAR_DESIGNER_KNOBS_SIZE, - POLAR_DESIGNER_KNOBS_SIZE, 1.0f); - - g.setColour (activeElem == i ? handle.colour.withSaturation(0.8) : handle.colour.withSaturation (0.2).withMultipliedAlpha (calcAlphaOfDirPath(handle))); - g.fillEllipse (circX - (POLAR_DESIGNER_KNOBS_SIZE / 2), - circY - (POLAR_DESIGNER_KNOBS_SIZE / 2), - POLAR_DESIGNER_KNOBS_SIZE, - POLAR_DESIGNER_KNOBS_SIZE); + bandKnobs[i].setBounds(circX - knobSize / 2, circY - knobSize / 2, knobSize, knobSize); - // align elements -#if 0 // !J! mergefix - handle.dirSlider->setBounds(circX + (handle.dirSlider->getWidth() + POLAR_DESIGNER_KNOBS_SIZE), - handle.dirSlider->getY(), - handle.dirSlider->getWidth(), handle.dirSlider->getHeight()); - handle.gainSlider->setBounds(circX + (handle.gainSlider->getWidth() + POLAR_DESIGNER_KNOBS_SIZE), - handle.gainSlider->getY(), - handle.gainSlider->getWidth(), handle.gainSlider->getHeight()); - - handle.muteButton->setTopLeftPosition(handle.gainSlider->getX(), handle.muteButton->getY()); - handle.soloButton->setTopLeftPosition(handle.gainSlider->getX() + - handle.gainSlider->getWidth() - - handle.soloButton->getWidth(), - handle.soloButton->getY()); - - handle.polarPatternVisualizer->setBounds(handle.gainSlider->getX(), handle.polarPatternVisualizer->getY(), - handle.polarPatternVisualizer->getWidth(), - handle.polarPatternVisualizer->getHeight()); - - handle.polarPatternVisualizer->setActive(true); -#endif - handle.polarPatternVisualizer->getParentComponent()->resized(); + if (!handle.dirSlider->isEnabled()) + { + bandKnobs[i].setEnabled(false); + } + else + { + bandKnobs[i].setEnabled(true); + } + if (bandKnobs[i].isEnabled() && (bandKnobs[i].isMouseOver() || tooltipValueKnobBox[i]->isMouseOver())) + { + int y = bandKnobs[i].getY() > dirToY(s.yMin - s.yMax) / 2 ? bandKnobs[i].getY() - bandKnobs[i].getHeight() - 5 : bandKnobs[i].getBottom() + 5; + drawTooltip(i, bandKnobs[i].getX() - 5, y, true); + } + else + tooltipValueKnobBox[i]->setVisible(false); -//#ifdef AA_DO_DEBUG_PATH -// { // !J! for debug purposes only -// -// debugPath.addStar(handle.polarPatternVisualizer->getScreenPosition().toFloat(), 8, 10, 20); -// debugPath.startNewSubPath(handle.polarPatternVisualizer->getBounds().getX(), -// handle.polarPatternVisualizer->getBounds().getY()); -// -// debugPath.lineTo(handle.polarPatternVisualizer->getBounds().getRight(), -// handle.polarPatternVisualizer->getBounds().getBottom()); -// -// debugPath.addRectangle(handle.polarPatternVisualizer->getBounds().getX(), handle.polarPatternVisualizer->getBounds().getY(), -// handle.polarPatternVisualizer->getBounds().getWidth(), handle.polarPatternVisualizer->getBounds().getHeight()); -// } -// -// { // !J! for debug purposes only -// -// debugPath.startNewSubPath(handle.handlePos.getX(), -// handle.handlePos.getY()); -// debugPath.addStar(handle.handlePos.toFloat(), 6, 5, 10); -// } -//#endif + // align elements + handle.polarPatternVisualizer->getParentComponent()->resized(); if (i < nrActiveBands - 1) { // draw tooltip showing frequency if (activeBandLimitPath == i || tooltipValueBox[i]->isMouseOver() || tooltipValueBox[i]->isBeingEdited()) - drawTooltip(i, rightBound-60, dirToY(s.yMax)-OH); + drawTooltip(i, rightBound-70, dirToY(s.yMax)-OH, false); else tooltipValueBox[i]->setVisible(false); } } - oldNrActiveBands = nrActiveBands; - -#ifdef AA_DO_DEBUG_PATH - g.strokePath (debugPath, PathStrokeType (5.0f)); // !J! -#endif - } float dirToY(const float dir) @@ -536,17 +565,17 @@ class DirectivityEQ : public Component, private Slider::Listener, private Label void mouseDrag(const MouseEvent &event) override { - if (!active) + if (!active || !event.eventComponent->isEnabled()) return; - - if (event.eventComponent->getName() == "RectangleComponent" || event.eventComponent == this) + + if (event.eventComponent->getName() == "RectangleComponent" || event.eventComponent->getName() == "BandKnobComponent" || event.eventComponent == this) { if (activeElem != -1) { // this improves rendering performance! for (auto& rec : dirPathRects) rec.setVisible(false); - + MouseEvent ev = event.getEventRelativeTo(this); Point pos = ev.getPosition(); float dirFactor = yToDir(pos.y); @@ -554,7 +583,7 @@ class DirectivityEQ : public Component, private Slider::Listener, private Label BandElements& handle(elements.getReference(activeElem)); if (handle.dirSlider != nullptr) setValueAndSnapToGrid(handle, dirFactor); - + // change all bands by holding alt key if (event.mods.isAltDown()) { @@ -563,18 +592,18 @@ class DirectivityEQ : public Component, private Slider::Listener, private Label if (elem.dirSlider != nullptr) setValueAndSnapToGrid(elem, dirFactor); } } - isDraggingDirPath = true; + dirSliderLastChangedByDrag = true; } } - else if (event.eventComponent->getName() == "PathComponent") + else if (event.eventComponent->getName() == "PathComponent" || event.eventComponent->getName() == "BandLimitDividerHolder") { if (activeBandLimitPath != -1) { MouseEvent ev = event.getEventRelativeTo(this); Point pos = ev.getPosition(); float frequency = xToHz(pos.x); - + BandElements& handle(elements.getReference(activeBandLimitPath)); Slider* slider = handle.upperFrequencySlider; if (slider != nullptr) @@ -590,67 +619,31 @@ class DirectivityEQ : public Component, private Slider::Listener, private Label { if (!active) return; - + int oldActiveElem = activeElem; - float oldActivePath = activePatternPath; int oldActiveBandLimitPath = activeBandLimitPath; activeElem = -1; - activePatternPath = -1; activeBandLimitPath = -1; - Point pos = event.getPosition(); +// Point pos = event.getPosition(); - if (event.eventComponent == this) - { - Point posf = Point(pos.getX(),pos.getY()); - - // highlight active polar pattern path - if (omniPath.getBounds().contains(posf)) - activePatternPath = omniFact; - else if (eightPath.getBounds().contains(posf)) - activePatternPath = eightFact; - else if (cardPath.getBounds().contains(posf)) - activePatternPath = cardFact; - else if (rCardPath.getBounds().contains(posf)) - activePatternPath = rCardFact; - else if (sCardPath.getBounds().contains(posf)) - activePatternPath = sCardFact; - else if (hCardPath.getBounds().contains(posf)) - activePatternPath = hCardFact; - else if (bCardPath.getBounds().contains(posf)) - activePatternPath = bCardFact; - else if (rbCardPath.getBounds().contains(posf)) - activePatternPath = rbCardFact; - - // highlight active pattern path if mouse is close to handle circle - for (int i = 0; i < nrActiveBands; i++) - { - BandElements& handle(elements.getReference(i)); - - if (pos.getDistanceSquaredFrom(handle.handlePos) < 140) - { - activeElem = i; - break; - } - } - } - else if (event.eventComponent->getName() == "RectangleComponent") + if (event.eventComponent->getName() == "RectangleComponent" || event.eventComponent->getName() == "BandKnobComponent") { // highlight active pattern path if mouse is on rectangle for (int i = 0; i < nrActiveBands; i++) { - if (event.eventComponent == &dirPathRects[i]) + if (event.eventComponent == &dirPathRects[i] || event.eventComponent == &bandKnobs[i]) { activeElem = i; break; } } } - else if (event.eventComponent->getName() == "PathComponent") + else if (event.eventComponent->getName() == "PathComponent" || event.eventComponent->getName() == "BandLimitDividerHolder") { // highlight active band limit path for (int i = 0; i < nrActiveBands - 1; i++) { - if (event.eventComponent == &bandLimitPaths[i]) + if (event.eventComponent == &bandLimitPaths[i] || event.eventComponent == &bandLimitDividerHolders[i]) { activeBandLimitPath = i; break; @@ -659,41 +652,32 @@ class DirectivityEQ : public Component, private Slider::Listener, private Label } if (oldActiveElem != activeElem - || oldActivePath != activePatternPath || oldActiveBandLimitPath != activeBandLimitPath) repaint(); } - + void mouseUp (const MouseEvent &event) override { // this improves rendering performance! if (isDraggingDirPath) { for (int i = 0; i < nrActiveBands; ++i) + { dirPathRects[i].setVisible(true); - + bandKnobs[i].setVisible(true); + } isDraggingDirPath = false; } - + if (!active || event.eventComponent != this) return; - - // set all patterns according to click on pattern symbol - if (activePatternPath != -1) - { - for (BandElements& elem : elements) - { - if (elem.dirSlider != nullptr) - elem.dirSlider->setValue(activePatternPath); - } - } } - + void mouseDoubleClick (const MouseEvent &event) override { if (!active || (event.eventComponent->getName() != "RectangleComponent" && event.eventComponent != this)) return; - + // set one band to omni for (int i = 0; i < nrActiveBands; ++i) { @@ -705,21 +689,20 @@ class DirectivityEQ : public Component, private Slider::Listener, private Label } } } - + void mouseExit (const MouseEvent &event) override { if (event.eventComponent == this) { - activePatternPath = -1; activeElem = -1; repaint(); } - else if (event.eventComponent->getName() == "RectangleComponent") + else if (event.eventComponent->getName() == "RectangleComponent" || event.eventComponent->getName() == "BandKnobComponent") { activeElem = -1; repaint(); } - else if (event.eventComponent->getName() == "PathComponent") + else if (event.eventComponent->getName() == "PathComponent" || event.eventComponent->getName() == "BandLimitDividerHolder") { activeBandLimitPath = -1; repaint(); @@ -731,15 +714,34 @@ class DirectivityEQ : public Component, private Slider::Listener, private Label if (!tooltip->isBeingEdited()) tooltip->setVisible(false); } + for (auto& tooltip : tooltipValueKnobBox) + { + if (!tooltip->isBeingEdited()) + tooltip->setVisible(false); + } + repaint(); } } void resized() override { + Rectangle area(getLocalBounds()); + int xMin = hzToX(s.fMin); int xMax = hzToX(s.fMax); numPixels = xMax - xMin + 1; + mT = area.proportionOfHeight(0.1f); + mB = area.proportionOfHeight(0.08f); + mL = area.proportionOfHeight(0.13f); + + if (SystemStats::getOperatingSystemName() == "iOS") + dirPatternButtonWidth = mL; + else + dirPatternButtonWidth = mL * 0.6f; + + dirPatternButtonHeight = mL * 0.5f; + frequencies.resize(numPixels); for (int i = 0; i < numPixels; ++i) frequencies.set(i, xToHz(xMin + i)); @@ -749,31 +751,44 @@ class DirectivityEQ : public Component, private Slider::Listener, private Label dirGridPath.clear(); dyn = s.yMax - s.yMin; int numgridlines = dyn/s.gridDiv+1; + for (int i=0; i < numgridlines; i++) { float db_val = s.yMax - i * s.gridDiv; int ypos = dirToY(db_val); - dirGridPath.startNewSubPath(mL-OH, ypos); - dirGridPath.lineTo(mL + width+OH, ypos); + dirGridPath.startNewSubPath(mL, ypos); + dirGridPath.lineTo(mL + width, ypos); + //Directivity primary buttons + tbPrimDirButtons[i].setBounds(5.f, ypos, dirPatternButtonWidth, dirPatternButtonHeight); + tbPrimDirButtons[i].setCentrePosition(mL/2, ypos); } - + // add grid for super card, hyper card and broad card + // and directivity secondary buttons smallDirGridPath.clear(); int ypos = dirToY(hCardFact); - smallDirGridPath.startNewSubPath(mL-OH, ypos); - smallDirGridPath.lineTo(mL + width+OH, ypos); - + smallDirGridPath.startNewSubPath(mL, ypos); + smallDirGridPath.lineTo(mL + width, ypos); + tbSecDirButtons[0].setBounds(5.f, ypos, dirPatternButtonWidth, dirPatternButtonHeight); + tbSecDirButtons[0].setCentrePosition(mL / 2, ypos); + ypos = dirToY(sCardFact); - smallDirGridPath.startNewSubPath(mL-OH, ypos); - smallDirGridPath.lineTo(mL + width+OH, ypos); - + smallDirGridPath.startNewSubPath(mL, ypos); + smallDirGridPath.lineTo(mL + width, ypos); + tbSecDirButtons[1].setBounds(5.f, ypos, dirPatternButtonWidth, dirPatternButtonHeight); + tbSecDirButtons[1].setCentrePosition(mL / 2, ypos); + ypos = dirToY(bCardFact); - smallDirGridPath.startNewSubPath(mL-OH, ypos); - smallDirGridPath.lineTo(mL + width+OH, ypos); - + smallDirGridPath.startNewSubPath(mL, ypos); + smallDirGridPath.lineTo(mL + width, ypos); + tbSecDirButtons[2].setBounds(5.f, ypos, dirPatternButtonWidth, dirPatternButtonHeight); + tbSecDirButtons[2].setCentrePosition(mL / 2, ypos); + ypos = dirToY(rbCardFact); - smallDirGridPath.startNewSubPath(mL-OH, ypos); - smallDirGridPath.lineTo(mL + width+OH, ypos); + smallDirGridPath.startNewSubPath(mL, ypos); + smallDirGridPath.lineTo(mL + width, ypos); + tbSecDirButtons[3].setBounds(5.f, ypos, dirPatternButtonWidth, dirPatternButtonHeight); + tbSecDirButtons[3].setCentrePosition(mL / 2, ypos); // frequency grid hzGridPath.clear(); @@ -783,25 +798,23 @@ class DirectivityEQ : public Component, private Slider::Listener, private Label if ((f == 20) || (f == 50) || (f == 100) || (f == 200) || (f == 500) || (f == 1000) || (f == 2000) || (f == 5000) || (f == 10000) || (f == 20000)) { - hzGridPathBold.startNewSubPath(xpos, dirToY(s.yMax)-OH); - hzGridPathBold.lineTo(xpos, dirToY(s.yMin)+OH); + hzGridPathBold.startNewSubPath(xpos, dirToY(s.yMax)); + hzGridPathBold.lineTo(xpos, dirToY(s.yMin)); } else { - hzGridPath.startNewSubPath(xpos, dirToY(s.yMax)-OH); - hzGridPath.lineTo(xpos, dirToY(s.yMin)+OH); + hzGridPath.startNewSubPath(xpos, dirToY(s.yMax)); + hzGridPath.lineTo(xpos, dirToY(s.yMin)); } } - initValueBox(); } - void addSliders(Colour newColour, Slider* dirSlider = nullptr, Slider* lowerFrequencySlider = nullptr, Slider* upperFrequencySlider = nullptr, MuteSoloButton* soloButton = nullptr, MuteSoloButton* muteButton = nullptr, Slider* gainSlider = nullptr, PolarPatternVisualizer* directivityVis = nullptr - ) + void addSliders(Colour newColour, Slider* dirSlider = nullptr, Slider* lowerFrequencySlider = nullptr, Slider* upperFrequencySlider = nullptr, ToggleButton* soloButton = nullptr, ToggleButton* muteButton = nullptr, Slider* gainSlider = nullptr, PolarPatternVisualizer* directivityVis = nullptr) { elements.add({dirSlider, lowerFrequencySlider, upperFrequencySlider, soloButton, muteButton, newColour, gainSlider, directivityVis}); } - + void setValueAndSnapToGrid(BandElements& elem, float dirFact) { float snapMargin = 0.035f; @@ -815,12 +828,12 @@ class DirectivityEQ : public Component, private Slider::Listener, private Label } elem.dirSlider->setValue(dirFact); } - + void setSoloActive(bool set) { soloActive = set; } - + float calcAlphaOfDirPath(BandElements& elem) { float maxGain = std::max(elem.gainSlider->getMaximum(), std::abs(elem.gainSlider->getMinimum())); @@ -844,13 +857,13 @@ class DirectivityEQ : public Component, private Slider::Listener, private Label return 2.0f/7.0f; } } - + void setActive(bool set) { active = set; repaint(); } - + void initValueBox() { auto& lf = getLookAndFeel(); @@ -860,9 +873,9 @@ class DirectivityEQ : public Component, private Slider::Listener, private Label Slider* slider = elements[i].upperFrequencySlider; if (slider == nullptr) continue; - + slider->addListener(this); - + tooltipValueBox[i].reset (lf.createSliderTextBox (*slider)); tooltipValueBox[i]->addMouseListener(this, false); tooltipValueBox[i]->addListener(this); @@ -871,19 +884,42 @@ class DirectivityEQ : public Component, private Slider::Listener, private Label tooltipValueBox[i]->setAlwaysOnTop (true); tooltipValueBox[i]->setEditable(true); } + + for (int i = 0; i < 5; ++i) + { + Slider* slider = elements[i].dirSlider; + if (slider == nullptr) + continue; + + slider->addListener(this); + + tooltipValueKnobBox[i].reset(lf.createSliderTextBox(*slider)); + tooltipValueKnobBox[i]->addMouseListener(this, false); + tooltipValueKnobBox[i]->addListener(this); + addChildComponent(tooltipValueKnobBox[i].get()); + tooltipValueKnobBox[i]->setText(slider->getTextFromValue(slider->getValue()), NotificationType::dontSendNotification); + tooltipValueKnobBox[i]->setAlwaysOnTop(true); + tooltipValueKnobBox[i]->setEditable(false); + } } - - void drawTooltip(int tooltipIndex, int xCoord, int yCoord) + + void drawTooltip(int tooltipIndex, int xCoord, int yCoord, bool isKnobTooltip) { - if (tooltipValueBox[tooltipIndex] == nullptr) + if (tooltipValueBox[tooltipIndex] == nullptr || tooltipValueKnobBox[tooltipIndex] == nullptr) return; - - int tooltipWidth = 60; - int tooltipHeight = 20; - tooltipValueBox[tooltipIndex]->setBounds (xCoord, yCoord, tooltipWidth, tooltipHeight); - tooltipValueBox[tooltipIndex]->setVisible (true); + + if (!isKnobTooltip) + { + tooltipValueBox[tooltipIndex]->setBounds(xCoord, yCoord, getTopLevelComponent()->getWidth() * 0.06f, getTopLevelComponent()->getHeight() * 0.03f); + tooltipValueBox[tooltipIndex]->setVisible(true); + } + else + { + tooltipValueKnobBox[tooltipIndex]->setBounds(xCoord, yCoord, getTopLevelComponent()->getWidth() * 0.04f, getTopLevelComponent()->getHeight() * 0.03f); + tooltipValueKnobBox[tooltipIndex]->setVisible(true); + } } - + void sliderValueChanged(Slider* slider) override { for (int i = 0; i < 4; ++i) @@ -892,8 +928,14 @@ class DirectivityEQ : public Component, private Slider::Listener, private Label if (slider == freqSlider && tooltipValueBox[i]->isVisible()) tooltipValueBox[i]->setText (slider->getTextFromValue(slider->getValue()), NotificationType::dontSendNotification); } + for (int i = 0; i < 5; ++i) + { + Slider* dSlider = elements[i].dirSlider; + if (slider == dSlider && tooltipValueKnobBox[i]->isVisible()) + tooltipValueKnobBox[i]->setText(slider->getTextFromValue(slider->getValue()), NotificationType::dontSendNotification); + } } - + void labelTextChanged (Label* label) override { for (int i = 0; i < 4; ++i) @@ -916,14 +958,14 @@ class DirectivityEQ : public Component, private Slider::Listener, private Label } } - + float getXoverValueInRange(int sliderNum, float attemptedValue) { float min = processor.getXoverSliderRangeStart(sliderNum); float max = processor.getXoverSliderRangeEnd(sliderNum); return attemptedValue < min ? min : (attemptedValue > max ? max : attemptedValue); } - + void resetTooltipTexts() { for (int i = 0; i < 4; ++i) @@ -932,53 +974,150 @@ class DirectivityEQ : public Component, private Slider::Listener, private Label if (slider != nullptr) tooltipValueBox[i]->setText (slider->getTextFromValue (slider->getValue()), NotificationType::dontSendNotification); } + for (int i = 0; i < 5; ++i) + { + Slider* slider = elements[i].dirSlider; + if (slider != nullptr) + tooltipValueKnobBox[i]->setText(slider->getTextFromValue(slider->getValue()), NotificationType::dontSendNotification); + } } - + PathComponent& getBandlimitPathComponent (int idx) { return bandLimitPaths[idx]; } - + RectangleComponent& getDirPathComponent (int idx) { return dirPathRects[idx]; } + void buttonClicked(Button* button) override + { + if (button == &tbPrimDirButtons[0]) + { + for (BandElements& elem : elements) + { + if (elem.dirSlider != nullptr && elem.dirSlider->isEnabled()) + elem.dirSlider->setValue(eightFact); + } + resetTooltipTexts(); + } + else if (button == &tbPrimDirButtons[1]) + { + for (BandElements& elem : elements) + { + if (elem.dirSlider != nullptr && elem.dirSlider->isEnabled()) + elem.dirSlider->setValue(cardFact); + } + resetTooltipTexts(); + } + else if (button == &tbPrimDirButtons[2]) + { + for (BandElements& elem : elements) + { + if (elem.dirSlider != nullptr && elem.dirSlider->isEnabled()) + elem.dirSlider->setValue(omniFact); + } + resetTooltipTexts(); + } + else if (button == &tbPrimDirButtons[3]) + { + for (BandElements& elem : elements) + { + if (elem.dirSlider != nullptr && elem.dirSlider->isEnabled()) + elem.dirSlider->setValue(rCardFact); + } + resetTooltipTexts(); + } + else if (button == &tbSecDirButtons[0]) + { + for (BandElements& elem : elements) + { + if (elem.dirSlider != nullptr && elem.dirSlider->isEnabled()) + elem.dirSlider->setValue(hCardFact); + } + resetTooltipTexts(); + } + else if (button == &tbSecDirButtons[1]) + { + for (BandElements& elem : elements) + { + if (elem.dirSlider != nullptr && elem.dirSlider->isEnabled()) + elem.dirSlider->setValue(sCardFact); + } + resetTooltipTexts(); + } + else if (button == &tbSecDirButtons[2]) + { + for (BandElements& elem : elements) + { + if (elem.dirSlider != nullptr && elem.dirSlider->isEnabled()) + elem.dirSlider->setValue(bCardFact); + } + resetTooltipTexts(); + } + else if (button == &tbSecDirButtons[3]) + { + for (BandElements& elem : elements) + { + if (elem.dirSlider != nullptr && elem.dirSlider->isEnabled()) + elem.dirSlider->setValue(rbCardFact); + } + resetTooltipTexts(); + } + } + + int getEqWidth() + { + return (hzToX(20000) - hzToX(20)); + } + + int getBandWidth(int band) + { + return bandsWidth[band]; + } + + bool isDirSliderLastChangedByDrag() + { + return dirSliderLastChangedByDrag; + } + + void setDirSliderLastChangedByDrag(bool changedByDrag) + { + dirSliderLastChangedByDrag = changedByDrag; + } + private: PolarDesignerAudioProcessor& processor; - + bool active = true; int activeElem = -1; int activeBandLimitPath = -1; - float activePatternPath = -1; int nrActiveBands; int oldNrActiveBands; float dyn, zero, scale; bool soloActive; bool isDraggingDirPath = false; - + bool dirSliderLastChangedByDrag = false; + Settings s; Path dirGridPath; Path hzGridPath; Path hzGridPathBold; Path dirPaths[5]; Path smallDirGridPath; - + + int dirPatternButtonWidth; + int dirPatternButtonHeight; + std::unique_ptr