@@ -1492,6 +1492,71 @@ int LookAndFeel_V2::getSliderPopupPlacement (Slider&) | |||||
| BubbleComponent::right; | | 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<int> 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<int> LookAndFeel_V2::getTooltipBounds (const String& tipText, Point<int> screenPos, Rectangle<int> parentArea) | Rectangle<int> LookAndFeel_V2::getTooltipBounds (const String& tipText, Point<int> screenPos, Rectangle<int> parentArea) | ||||
{ | { | ||||
@@ -193,6 +193,7 @@ public: | |||||
ImageEffectFilter* getSliderEffect (Slider&) override; | ImageEffectFilter* getSliderEffect (Slider&) override; | ||||
Font getSliderPopupFont (Slider&) override; | Font getSliderPopupFont (Slider&) override; | ||||
int getSliderPopupPlacement (Slider&) override; | int getSliderPopupPlacement (Slider&) override; | ||||
Slider::SliderLayout getSliderLayout (Slider&) override; | |||||
//============================================================================== | //============================================================================== | ||||
Rectangle<int> getTooltipBounds (const String& tipText, Point<int> screenPos, Rectangle<int> parentArea) override; | Rectangle<int> getTooltipBounds (const String& tipText, Point<int> screenPos, Rectangle<int> parentArea) override; | ||||
@@ -99,6 +99,12 @@ public: | |||||
|| style == RotaryHorizontalVerticalDrag; | || style == RotaryHorizontalVerticalDrag; | ||||
} | } | ||||
bool isBar() const noexcept | |||||
{ | |||||
return style == LinearBar | |||||
|| style == LinearBarVertical; | |||||
} | |||||
bool incDecDragDirectionIsHorizontal() const noexcept | bool incDecDragDirectionIsHorizontal() const noexcept | ||||
{ | { | ||||
return incDecButtonMode == incDecButtonsDraggable_Horizontal | return incDecButtonMode == incDecButtonsDraggable_Horizontal | ||||
@@ -740,7 +746,7 @@ public: | |||||
void handleAbsoluteDrag (const MouseEvent& e) | void handleAbsoluteDrag (const MouseEvent& e) | ||||
{ | { | ||||
const float mousePos = (isHorizontal() || style == RotaryHorizontalDrag) ? e.position.x : e.position.y; | const float mousePos = (isHorizontal() || style == RotaryHorizontalDrag) ? e.position.x : e.position.y; | ||||
double newPos = (mousePos - sliderRegionStart) / (double) sliderRegionSize; | |||||
double newPos = 0; | |||||
if (style == RotaryHorizontalDrag | if (style == RotaryHorizontalDrag | ||||
|| style == RotaryVerticalDrag | || style == RotaryVerticalDrag | ||||
@@ -774,6 +780,8 @@ public: | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
newPos = (mousePos - sliderRegionStart) / (double) sliderRegionSize; | |||||
if (isVertical()) | if (isVertical()) | ||||
newPos = 1.0 - newPos; | newPos = 1.0 - newPos; | ||||
} | } | ||||
@@ -1120,98 +1128,34 @@ public: | |||||
} | } | ||||
} | } | ||||
void resized (const Rectangle<int>& 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()) | 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(); | resizeIncDecButtons(); | ||||
} | |||||
} | } | ||||
//============================================================================== | |||||
void resizeIncDecButtons() | void resizeIncDecButtons() | ||||
{ | { | ||||
Rectangle<int> buttonRect (sliderRect); | Rectangle<int> buttonRect (sliderRect); | ||||
@@ -1582,12 +1526,13 @@ void Slider::setScrollWheelEnabled (const bool enabled) { pimpl->scrollWheel | |||||
bool Slider::isHorizontal() const noexcept { return pimpl->isHorizontal(); } | bool Slider::isHorizontal() const noexcept { return pimpl->isHorizontal(); } | ||||
bool Slider::isVertical() const noexcept { return pimpl->isVertical(); } | bool Slider::isVertical() const noexcept { return pimpl->isVertical(); } | ||||
bool Slider::isRotary() const noexcept { return pimpl->isRotary(); } | 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); } | float Slider::getPositionOfValue (const double value) { return pimpl->getPositionOfValue (value); } | ||||
//============================================================================== | //============================================================================== | ||||
void Slider::paint (Graphics& g) { pimpl->paint (g, getLookAndFeel()); } | 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(); } | void Slider::focusOfChildComponentChanged (FocusChangeType) { repaint(); } | ||||
@@ -756,6 +756,8 @@ public: | |||||
bool isVertical() const noexcept; | bool isVertical() const noexcept; | ||||
/** True if the slider is in a rotary mode. */ | /** True if the slider is in a rotary mode. */ | ||||
bool isRotary() const noexcept; | 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. | /** 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. */ | 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<int> sliderBounds; | |||||
Rectangle<int> textBoxBounds; | |||||
}; | |||||
//============================================================================== | //============================================================================== | ||||
/** This abstract base class is implemented by LookAndFeel classes to provide | /** This abstract base class is implemented by LookAndFeel classes to provide | ||||
slider drawing functionality. | slider drawing functionality. | ||||
@@ -830,6 +842,8 @@ public: | |||||
virtual Font getSliderPopupFont (Slider&) = 0; | virtual Font getSliderPopupFont (Slider&) = 0; | ||||
virtual int getSliderPopupPlacement (Slider&) = 0; | virtual int getSliderPopupPlacement (Slider&) = 0; | ||||
virtual SliderLayout getSliderLayout (Slider&) = 0; | |||||
#if JUCE_CATCH_DEPRECATED_CODE_MISUSE | #if JUCE_CATCH_DEPRECATED_CODE_MISUSE | ||||
// These methods' parameters have changed: see the new method signatures. | // These methods' parameters have changed: see the new method signatures. | ||||
virtual void createSliderButton (bool) {} | virtual void createSliderButton (bool) {} | ||||