This has been a long standing pet peeve of mine. Mouse scroll events trigger many value changes, each of which have their own start and end signals, which clog the undo manager.
I have a few ways of side stepping this, but it’s always a bit ugly. Is there any chance the JUCE team could look at patching slider to batch these events together at the source?
The below works, however I do not fully understand the effects this may have on other functionality.
In juce_Slider.cpp, we have this code inside bool mouseWheelMove (const MouseEvent& e, const MouseWheelDetails& wheel)
auto newValue = value + jmax (normRange.interval, std::abs (delta)) * (delta < 0 ? -1.0 : 1.0);
std::unique_ptr< ScopedDragNotification> drag;
setValue (owner.snapValue (newValue, notDragging), sendNotificationSync);
And this is where the issue really starts. Each little fragment of a scroll wheel move will create a new ScopedDragNotification which will very shortly go out of scope and complete an interaction with the slider, and enter that move into the undo queue.
I propose something like this (this was quick and hacky!)
struct DragTimeout : public Timer
{
void signal(Slider& owner)
{
if (!drag)
drag = std::make_unique<ScopedDragNotification>(owner);
startTimer(500);
}
void timerCallback() override
{
stopTimer();
drag.reset();
}
std::unique_ptr< ScopedDragNotification> drag;
};
And then replace the existing code with:
auto newValue = value + jmax (normRange.interval, std::abs (delta)) * (delta < 0 ? -1.0 : 1.0);
dragSignaller.signal(owner);
setValue (owner.snapValue (newValue, notDragging), sendNotificationSync);
This seems to work, and no more manual workarounds. This can be further fine tuned to leverage mouse down and exits to rely less on a timeout and ensure the entire scroll activity is treated as one move.
Am I on to something here, or am I overlooking something that will break?
