diff --git a/modules/juce_gui_basics/widgets/juce_Slider.cpp b/modules/juce_gui_basics/widgets/juce_Slider.cpp index e949bb559e..4ae5d7953f 100644 --- a/modules/juce_gui_basics/widgets/juce_Slider.cpp +++ b/modules/juce_gui_basics/widgets/juce_Slider.cpp @@ -33,7 +33,7 @@ public: : owner (owner_), style (style_), lastCurrentValue (0), lastValueMin (0), lastValueMax (0), - minimum (0), maximum (10), interval (0), + minimum (0), maximum (10), interval (0), doubleClickReturnValue (0), skewFactor (1.0), velocityModeSensitivity (1.0), velocityModeOffset (0.0), velocityModeThreshold (1), rotaryStart (float_Pi * 1.2f), @@ -69,7 +69,7 @@ public: } //============================================================================== - void init() + void registerListeners() { currentValue.addListener (this); valueMin.addListener (this); @@ -91,7 +91,21 @@ public: || style == ThreeValueVertical; } - float getPositionOfValue (const double value) + bool isRotary() const noexcept + { + return style == Rotary + || style == RotaryHorizontalDrag + || style == RotaryVerticalDrag + || style == RotaryHorizontalVerticalDrag; + } + + bool incDecDragDirectionIsHorizontal() const noexcept + { + return incDecButtonMode == incDecButtonsDraggable_Horizontal + || (incDecButtonMode == incDecButtonsDraggable_AutoDirection && incDecButtonsSideBySide); + } + + float getPositionOfValue (const double value) const { if (isHorizontal() || isVertical()) { @@ -104,13 +118,9 @@ public: } } - void setRange (const double newMin, - const double newMax, - const double newInt) + void setRange (const double newMin, const double newMax, const double newInt) { - if (minimum != newMin - || maximum != newMax - || interval != newInt) + if (minimum != newMin || maximum != newMax || interval != newInt) { minimum = newMin; maximum = newMax; @@ -155,9 +165,7 @@ public: return currentValue.getValue(); } - void setValue (double newValue, - const bool sendUpdateMessage, - const bool sendMessageSynchronously) + void setValue (double newValue, const bool sendUpdateMessage, const bool sendMessageSynchronously) { // for a two-value style slider, you should use the setMinValue() and setMaxValue() // methods to set the two values. @@ -235,7 +243,8 @@ public: } } - void setMaxValue (double newValue, const bool sendUpdateMessage, const bool sendMessageSynchronously, const bool allowNudgingOfOtherValues) + void setMaxValue (double newValue, const bool sendUpdateMessage, + const bool sendMessageSynchronously, const bool allowNudgingOfOtherValues) { // The maximum value only applies to sliders that are in two- or three-value mode. jassert (style == TwoValueHorizontal || style == TwoValueVertical @@ -358,13 +367,10 @@ public: { if (style == IncDecButtons) { - sendDragStart(); - - if (button == incButton) - setValue (owner.snapValue (getValue() + interval, false), true, true); - else if (button == decButton) - setValue (owner.snapValue (getValue() - interval, false), true, true); + const double delta = (button == incButton) ? interval : -interval; + sendDragStart(); + setValue (owner.snapValue (getValue() + delta, false), true, true); sendDragEnd(); } } @@ -415,35 +421,35 @@ public: return value; } - float getLinearSliderPos (const double value) + float getLinearSliderPos (const double value) const { - double sliderPosProportional; + double pos; if (maximum > minimum) { if (value < minimum) { - sliderPosProportional = 0.0; + pos = 0.0; } else if (value > maximum) { - sliderPosProportional = 1.0; + pos = 1.0; } else { - sliderPosProportional = owner.valueToProportionOfLength (value); - jassert (sliderPosProportional >= 0 && sliderPosProportional <= 1.0); + pos = owner.valueToProportionOfLength (value); + jassert (pos >= 0 && pos <= 1.0); } } else { - sliderPosProportional = 0.5; + pos = 0.5; } if (isVertical() || style == IncDecButtons) - sliderPosProportional = 1.0 - sliderPosProportional; + pos = 1.0 - pos; - return (float) (sliderRegionStart + sliderPosProportional * sliderRegionSize); + return (float) (sliderRegionStart + pos * sliderRegionSize); } void setSliderStyle (const SliderStyle newStyle) @@ -617,35 +623,46 @@ public: owner.repaint(); } - bool incDecDragDirectionIsHorizontal() const - { - return incDecButtonMode == incDecButtonsDraggable_Horizontal - || (incDecButtonMode == incDecButtonsDraggable_AutoDirection && incDecButtonsSideBySide); - } - void showPopupMenu() { menuShown = true; PopupMenu m; m.setLookAndFeel (&owner.getLookAndFeel()); - m.addItem (1, TRANS ("velocity-sensitive mode"), true, isVelocityBased); + m.addItem (1, TRANS ("Velocity-sensitive mode"), true, isVelocityBased); m.addSeparator(); - if (style == Rotary || style == RotaryHorizontalDrag || style == RotaryVerticalDrag) + if (isRotary()) { PopupMenu rotaryMenu; - rotaryMenu.addItem (2, TRANS ("use circular dragging"), true, style == Rotary); - rotaryMenu.addItem (3, TRANS ("use left-right dragging"), true, style == RotaryHorizontalDrag); - rotaryMenu.addItem (4, TRANS ("use up-down dragging"), true, style == RotaryVerticalDrag); + rotaryMenu.addItem (2, TRANS ("Use circular dragging"), true, style == Rotary); + rotaryMenu.addItem (3, TRANS ("Use left-right dragging"), true, style == RotaryHorizontalDrag); + rotaryMenu.addItem (4, TRANS ("Use up-down dragging"), true, style == RotaryVerticalDrag); + rotaryMenu.addItem (5, TRANS ("Use left-right/up-down dragging"), true, style == RotaryHorizontalVerticalDrag); - m.addSubMenu (TRANS ("rotary mode"), rotaryMenu); + m.addSubMenu (TRANS ("Rotary mode"), rotaryMenu); } m.showMenuAsync (PopupMenu::Options(), ModalCallbackFunction::forComponent (sliderMenuCallback, &owner)); } + static void sliderMenuCallback (const int result, Slider* slider) + { + if (slider != nullptr) + { + switch (result) + { + case 1: slider->setVelocityBasedMode (! slider->getVelocityBasedMode()); break; + case 2: slider->setSliderStyle (Rotary); break; + case 3: slider->setSliderStyle (RotaryHorizontalDrag); break; + case 4: slider->setSliderStyle (RotaryVerticalDrag); break; + case 5: slider->setSliderStyle (RotaryHorizontalVerticalDrag); break; + default: break; + } + } + } + int getThumbIndexAt (const MouseEvent& e) { const bool isTwoValue = (style == TwoValueHorizontal || style == TwoValueVertical); @@ -722,8 +739,7 @@ public: void handleAbsoluteDrag (const MouseEvent& e) { const int mousePos = (isHorizontal() || style == RotaryHorizontalDrag) ? e.x : e.y; - - double scaledMousePos = (mousePos - sliderRegionStart) / (double) sliderRegionSize; + double newPos = (mousePos - sliderRegionStart) / (double) sliderRegionSize; if (style == RotaryHorizontalDrag || style == RotaryVerticalDrag @@ -738,10 +754,8 @@ public: ? e.x - mouseDragStartPos.x : mouseDragStartPos.y - e.y; - double newPos = owner.valueToProportionOfLength (valueOnMouseDown) - + mouseDiff * (1.0 / pixelsForFullDragExtent); - - valueWhenLastDragged = owner.proportionOfLengthToValue (jlimit (0.0, 1.0, newPos)); + newPos = owner.valueToProportionOfLength (valueOnMouseDown) + + mouseDiff * (1.0 / pixelsForFullDragExtent); if (style == IncDecButtons) { @@ -749,21 +763,31 @@ public: decButton->setState (mouseDiff > 0 ? Button::buttonNormal : Button::buttonDown); } } + else if (style == RotaryHorizontalVerticalDrag) + { + const int mouseDiff = (e.x - mouseDragStartPos.x) + (mouseDragStartPos.y - e.y); + + newPos = owner.valueToProportionOfLength (valueOnMouseDown) + + mouseDiff * (1.0 / pixelsForFullDragExtent); + } else { if (isVertical()) - scaledMousePos = 1.0 - scaledMousePos; - - valueWhenLastDragged = owner.proportionOfLengthToValue (jlimit (0.0, 1.0, scaledMousePos)); + newPos = 1.0 - newPos; } + + valueWhenLastDragged = owner.proportionOfLengthToValue (jlimit (0.0, 1.0, newPos)); } void handleVelocityDrag (const MouseEvent& e) { - const int mouseDiff = (isHorizontal() || style == RotaryHorizontalDrag - || (style == IncDecButtons && incDecDragDirectionIsHorizontal())) - ? e.x - mousePosWhenLastDragged.x - : e.y - mousePosWhenLastDragged.y; + const int mouseDiff = style == RotaryHorizontalVerticalDrag + ? (e.x - mousePosWhenLastDragged.x) + (mousePosWhenLastDragged.y - e.y) + : (isHorizontal() + || style == RotaryHorizontalDrag + || (style == IncDecButtons && incDecDragDirectionIsHorizontal())) + ? e.x - mousePosWhenLastDragged.x + : e.y - mousePosWhenLastDragged.y; const double maxSpeed = jmax (200, sliderRegionSize); double speed = jlimit (0.0, maxSpeed, (double) abs (mouseDiff)); @@ -998,22 +1022,16 @@ public: : (double) currentValue.getValue()); Point mousePos; - if (style == RotaryHorizontalDrag || style == RotaryVerticalDrag) + if (isRotary()) { mousePos = Desktop::getLastMouseDownPosition(); - if (style == RotaryHorizontalDrag) - { - const double posDiff = owner.valueToProportionOfLength (pos) - - owner.valueToProportionOfLength (valueOnMouseDown); - mousePos += Point (roundToInt (pixelsForFullDragExtent * posDiff), 0); - } - else - { - const double posDiff = owner.valueToProportionOfLength (valueOnMouseDown) - - owner.valueToProportionOfLength (pos); - mousePos += Point (0, roundToInt (pixelsForFullDragExtent * posDiff)); - } + const int delta = roundToInt (pixelsForFullDragExtent * (owner.valueToProportionOfLength (valueOnMouseDown) + - owner.valueToProportionOfLength (pos))); + + if (style == RotaryHorizontalDrag) mousePos += Point (-delta, 0); + else if (style == RotaryVerticalDrag) mousePos += Point (0, delta); + else mousePos += Point (delta / -2, delta / 2); } else { @@ -1032,7 +1050,7 @@ public: { if (style != IncDecButtons) { - if (style == Rotary || style == RotaryHorizontalDrag || style == RotaryVerticalDrag) + if (isRotary()) { const float sliderPos = (float) owner.valueToProportionOfLength (lastCurrentValue); jassert (sliderPos >= 0 && sliderPos <= 1.0f); @@ -1268,21 +1286,6 @@ public: std::abs (a1 + double_Pi * 2.0 - a2), std::abs (a2 + double_Pi * 2.0 - a1)); } - - static void sliderMenuCallback (const int result, Slider* slider) - { - if (slider != nullptr) - { - switch (result) - { - case 1: slider->setVelocityBasedMode (! slider->getVelocityBasedMode()); break; - case 2: slider->setSliderStyle (Rotary); break; - case 3: slider->setSliderStyle (RotaryHorizontalDrag); break; - case 4: slider->setSliderStyle (RotaryVerticalDrag); break; - default: break; - } - } - } }; @@ -1312,7 +1315,7 @@ void Slider::init (SliderStyle style, TextEntryBoxPosition textBoxPos) Slider::lookAndFeelChanged(); updateText(); - pimpl->init(); + pimpl->registerListeners(); } Slider::~Slider() {} diff --git a/modules/juce_gui_basics/widgets/juce_Slider.h b/modules/juce_gui_basics/widgets/juce_Slider.h index aedd9da352..b0e3b35184 100644 --- a/modules/juce_gui_basics/widgets/juce_Slider.h +++ b/modules/juce_gui_basics/widgets/juce_Slider.h @@ -61,28 +61,30 @@ public: */ enum SliderStyle { - LinearHorizontal, /**< A traditional horizontal slider. */ - LinearVertical, /**< A traditional vertical slider. */ - LinearBar, /**< A horizontal bar slider with the text label drawn on top of it. */ - Rotary, /**< A rotary control that you move by dragging the mouse in a circular motion, like a knob. - @see setRotaryParameters */ - RotaryHorizontalDrag, /**< A rotary control that you move by dragging the mouse left-to-right. - @see setRotaryParameters */ - RotaryVerticalDrag, /**< A rotary control that you move by dragging the mouse up-and-down. - @see setRotaryParameters */ - IncDecButtons, /**< A pair of buttons that increment or decrement the slider's value by the increment set in setRange(). */ - - TwoValueHorizontal, /**< A horizontal slider that has two thumbs instead of one, so it can show a minimum and maximum value. - @see setMinValue, setMaxValue */ - TwoValueVertical, /**< A vertical slider that has two thumbs instead of one, so it can show a minimum and maximum value. - @see setMinValue, setMaxValue */ - - ThreeValueHorizontal, /**< A horizontal slider that has three thumbs instead of one, so it can show a minimum and maximum - value, with the current value being somewhere between them. - @see setMinValue, setMaxValue */ - ThreeValueVertical, /**< A vertical slider that has three thumbs instead of one, so it can show a minimum and maximum - value, with the current value being somewhere between them. - @see setMinValue, setMaxValue */ + LinearHorizontal, /**< A traditional horizontal slider. */ + LinearVertical, /**< A traditional vertical slider. */ + LinearBar, /**< A horizontal bar slider with the text label drawn on top of it. */ + Rotary, /**< A rotary control that you move by dragging the mouse in a circular motion, like a knob. + @see setRotaryParameters */ + RotaryHorizontalDrag, /**< A rotary control that you move by dragging the mouse left-to-right. + @see setRotaryParameters */ + RotaryVerticalDrag, /**< A rotary control that you move by dragging the mouse up-and-down. + @see setRotaryParameters */ + RotaryHorizontalVerticalDrag, /**< A rotary control that you move by dragging the mouse up-and-down or left-to-right. + @see setRotaryParameters */ + IncDecButtons, /**< A pair of buttons that increment or decrement the slider's value by the increment set in setRange(). */ + + TwoValueHorizontal, /**< A horizontal slider that has two thumbs instead of one, so it can show a minimum and maximum value. + @see setMinValue, setMaxValue */ + TwoValueVertical, /**< A vertical slider that has two thumbs instead of one, so it can show a minimum and maximum value. + @see setMinValue, setMaxValue */ + + ThreeValueHorizontal, /**< A horizontal slider that has three thumbs instead of one, so it can show a minimum and maximum + value, with the current value being somewhere between them. + @see setMinValue, setMaxValue */ + ThreeValueVertical, /**< A vertical slider that has three thumbs instead of one, so it can show a minimum and maximum + value, with the current value being somewhere between them. + @see setMinValue, setMaxValue */ }; /** The position of the slider's text-entry box.