diff --git a/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp b/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp index 28a9760ff6..756f146fe3 100644 --- a/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp +++ b/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp @@ -1492,6 +1492,71 @@ int LookAndFeel_V2::getSliderPopupPlacement (Slider&) | BubbleComponent::right; } +//============================================================================== +Slider::SliderLayout LookAndFeel_V2::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; + + Slider::TextEntryBoxPosition textBoxPos = slider.getTextBoxPosition(); + + if (textBoxPos == Slider::TextBoxLeft || textBoxPos == Slider::TextBoxRight) + minXSpace = 30; + else + minYSpace = 15; + + Rectangle localBounds = slider.getLocalBounds(); + + const int textBoxWidth = jmax (0, jmin (slider.getTextBoxWidth(), localBounds.getWidth() - minXSpace)); + const int textBoxHeight = jmax (0, jmin (slider.getTextBoxHeight(), localBounds.getHeight() - minYSpace)); + + Slider::SliderStyle style = slider.getSliderStyle(); + Slider::SliderLayout layout; + + // 2. set the textBox bounds + + if (textBoxPos != Slider::NoTextBox) + { + if (style == Slider::LinearBar || style == Slider::LinearBarVertical) + { + layout.textBoxBounds = localBounds; + } + else + { + layout.textBoxBounds.setWidth (textBoxWidth); + layout.textBoxBounds.setHeight (textBoxHeight); + + if (textBoxPos == Slider::TextBoxLeft) layout.textBoxBounds.setX (0); + else if (textBoxPos == Slider::TextBoxRight) layout.textBoxBounds.setX (localBounds.getWidth() - textBoxWidth); + 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 /* left or right -> centre vertically */ layout.textBoxBounds.setY ((localBounds.getHeight() - textBoxHeight) / 2); + } + } + + // 3. set the slider bounds + + layout.sliderBounds = localBounds; + + if (! slider.isBar()) + { + 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); + } + + if (slider.isBar()) layout.sliderBounds.reduce (1, 1); // bar indent + else if (slider.isHorizontal()) layout.sliderBounds.reduce (getSliderThumbRadius (slider), 0); + else if (slider.isVertical()) layout.sliderBounds.reduce (0, getSliderThumbRadius (slider)); + + return layout; +} + //============================================================================== Rectangle LookAndFeel_V2::getTooltipBounds (const String& tipText, Point screenPos, Rectangle parentArea) { diff --git a/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.h b/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.h index e4f25bb399..40ccad202b 100644 --- a/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.h +++ b/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.h @@ -193,6 +193,7 @@ public: ImageEffectFilter* getSliderEffect (Slider&) override; Font getSliderPopupFont (Slider&) override; int getSliderPopupPlacement (Slider&) override; + Slider::SliderLayout getSliderLayout (Slider&) override; //============================================================================== Rectangle getTooltipBounds (const String& tipText, Point screenPos, Rectangle parentArea) override; diff --git a/modules/juce_gui_basics/widgets/juce_Slider.cpp b/modules/juce_gui_basics/widgets/juce_Slider.cpp index 0d4f0da5b2..1f9389d330 100644 --- a/modules/juce_gui_basics/widgets/juce_Slider.cpp +++ b/modules/juce_gui_basics/widgets/juce_Slider.cpp @@ -99,6 +99,12 @@ public: || style == RotaryHorizontalVerticalDrag; } + bool isBar() const noexcept + { + return style == LinearBar + || style == LinearBarVertical; + } + bool incDecDragDirectionIsHorizontal() const noexcept { return incDecButtonMode == incDecButtonsDraggable_Horizontal @@ -740,7 +746,7 @@ public: void handleAbsoluteDrag (const MouseEvent& e) { const float mousePos = (isHorizontal() || style == RotaryHorizontalDrag) ? e.position.x : e.position.y; - double newPos = (mousePos - sliderRegionStart) / (double) sliderRegionSize; + double newPos = 0; if (style == RotaryHorizontalDrag || style == RotaryVerticalDrag @@ -774,6 +780,8 @@ public: } else { + newPos = (mousePos - sliderRegionStart) / (double) sliderRegionSize; + if (isVertical()) newPos = 1.0 - newPos; } @@ -1120,98 +1128,34 @@ public: } } - void resized (const Rectangle& localBounds, LookAndFeel& lf) + //============================================================================== + void resized (LookAndFeel& lf) { - int minXSpace = 0; - int minYSpace = 0; + SliderLayout layout = lf.getSliderLayout (owner); - if (textBoxPos == TextBoxLeft || textBoxPos == TextBoxRight) - minXSpace = 30; - else - minYSpace = 15; - - const int tbw = jmax (0, jmin (textBoxWidth, localBounds.getWidth() - minXSpace)); - const int tbh = jmax (0, jmin (textBoxHeight, localBounds.getHeight() - minYSpace)); + sliderRect = layout.sliderBounds; - if (style == LinearBar || style == LinearBarVertical) - { - if (valueBox != nullptr) - valueBox->setBounds (localBounds); - } - else - { - if (textBoxPos == NoTextBox) - { - sliderRect = localBounds; - } - else if (textBoxPos == TextBoxLeft) - { - valueBox->setBounds (0, (localBounds.getHeight() - tbh) / 2, tbw, tbh); - sliderRect.setBounds (tbw, 0, localBounds.getWidth() - tbw, localBounds.getHeight()); - } - else if (textBoxPos == TextBoxRight) - { - valueBox->setBounds (localBounds.getWidth() - tbw, (localBounds.getHeight() - tbh) / 2, tbw, tbh); - sliderRect.setBounds (0, 0, localBounds.getWidth() - tbw, localBounds.getHeight()); - } - else if (textBoxPos == TextBoxAbove) - { - valueBox->setBounds ((localBounds.getWidth() - tbw) / 2, 0, tbw, tbh); - sliderRect.setBounds (0, tbh, localBounds.getWidth(), localBounds.getHeight() - tbh); - } - else if (textBoxPos == TextBoxBelow) - { - valueBox->setBounds ((localBounds.getWidth() - tbw) / 2, localBounds.getHeight() - tbh, tbw, tbh); - sliderRect.setBounds (0, 0, localBounds.getWidth(), localBounds.getHeight() - tbh); - } - } - - const int indent = lf.getSliderThumbRadius (owner); - - if (style == LinearBar) - { - const int barIndent = 1; - sliderRegionStart = barIndent; - sliderRegionSize = localBounds.getWidth() - barIndent * 2; - - sliderRect.setBounds (sliderRegionStart, barIndent, - sliderRegionSize, localBounds.getHeight() - barIndent * 2); - } - else if (style == LinearBarVertical) - { - const int barIndent = 1; - sliderRegionStart = barIndent; - sliderRegionSize = localBounds.getHeight() - barIndent * 2; + if (valueBox != nullptr) + valueBox->setBounds (layout.textBoxBounds); - sliderRect.setBounds (barIndent, sliderRegionStart, - localBounds.getWidth() - barIndent * 2, sliderRegionSize); - } - else if (isHorizontal()) + if (isHorizontal()) { - sliderRegionStart = sliderRect.getX() + indent; - sliderRegionSize = jmax (1, sliderRect.getWidth() - indent * 2); - - sliderRect.setBounds (sliderRegionStart, sliderRect.getY(), - sliderRegionSize, sliderRect.getHeight()); + sliderRegionStart = layout.sliderBounds.getX(); + sliderRegionSize = layout.sliderBounds.getWidth(); } else if (isVertical()) { - sliderRegionStart = sliderRect.getY() + indent; - sliderRegionSize = jmax (1, sliderRect.getHeight() - indent * 2); - - sliderRect.setBounds (sliderRect.getX(), sliderRegionStart, - sliderRect.getWidth(), sliderRegionSize); + sliderRegionStart = layout.sliderBounds.getY(); + sliderRegionSize = layout.sliderBounds.getHeight(); } - else + else if (style == IncDecButtons) { - sliderRegionStart = 0; - sliderRegionSize = 100; - } - - if (style == IncDecButtons) resizeIncDecButtons(); + } } + //============================================================================== + void resizeIncDecButtons() { Rectangle buttonRect (sliderRect); @@ -1582,12 +1526,13 @@ void Slider::setScrollWheelEnabled (const bool enabled) { pimpl->scrollWheel bool Slider::isHorizontal() const noexcept { return pimpl->isHorizontal(); } bool Slider::isVertical() const noexcept { return pimpl->isVertical(); } bool Slider::isRotary() const noexcept { return pimpl->isRotary(); } +bool Slider::isBar() const noexcept { return pimpl->isBar(); } float Slider::getPositionOfValue (const double value) { return pimpl->getPositionOfValue (value); } //============================================================================== void Slider::paint (Graphics& g) { pimpl->paint (g, getLookAndFeel()); } -void Slider::resized() { pimpl->resized (getLocalBounds(), getLookAndFeel()); } +void Slider::resized() { pimpl->resized (getLookAndFeel()); } void Slider::focusOfChildComponentChanged (FocusChangeType) { repaint(); } diff --git a/modules/juce_gui_basics/widgets/juce_Slider.h b/modules/juce_gui_basics/widgets/juce_Slider.h index 8d3e912b65..695819c7ef 100644 --- a/modules/juce_gui_basics/widgets/juce_Slider.h +++ b/modules/juce_gui_basics/widgets/juce_Slider.h @@ -756,6 +756,8 @@ public: bool isVertical() const noexcept; /** True if the slider is in a rotary mode. */ bool isRotary() const noexcept; + /** True if the slider is in a linear bar mode. */ + bool isBar() const noexcept; //============================================================================== /** A set of colour IDs to use to change the colour of various aspects of the slider. @@ -780,6 +782,16 @@ public: textBoxOutlineColourId = 0x1001700 /**< The colour to use for a border around the text-editor box. */ }; + //============================================================================== + /** A struct defining the placement of the slider area and the text box area + relative to the bounds of the whole Slider component. + */ + struct SliderLayout + { + Rectangle sliderBounds; + Rectangle textBoxBounds; + }; + //============================================================================== /** This abstract base class is implemented by LookAndFeel classes to provide slider drawing functionality. @@ -830,6 +842,8 @@ public: virtual Font getSliderPopupFont (Slider&) = 0; virtual int getSliderPopupPlacement (Slider&) = 0; + virtual SliderLayout getSliderLayout (Slider&) = 0; + #if JUCE_CATCH_DEPRECATED_CODE_MISUSE // These methods' parameters have changed: see the new method signatures. virtual void createSliderButton (bool) {}