jimc
April 16, 2019, 2:39pm
1
I’ve got a viewport inside a viewport. The inner viewport i want to respond to horizontal scroll events but if a vertical scroll happens i want to scroll the outer one.
At the moment if the mouse is over the inner viewport it scrolls horizontally whether i drag vertically or horizontally on the trackpad.
It’s rows of album covers, a bit like netflix…
Any ideas?
jimc
April 17, 2019, 4:13pm
2
Is this a hard question or just incomprehensible?
Do you have the correct setScrollBarsShown config for each Viewport?
jimc
April 17, 2019, 4:30pm
4
The inner one is correct: I’ve disabled all the vertical scrolling options.
I’m not sure what the answer is. I had a similar setup with a Midi editor, with an inner Viewport with vertical scrolling for Midi notes, and the outer Viewport with horizontal scrolling for time, and I don’t recall having any issues… I’ll try to go back and look at the code…
jimc
April 17, 2019, 4:42pm
6
Thanks! Interesting if it worked for you. Unless its’ a new JUCE thing, we are on some older build, I’ll check the JUCE commits…
Looking back, the horizontal (time) viewport was inside the vertical (note) viewport. And here are the setScrollBarsShown lines:
midiEditorVerticalViewport->setScrollBarsShown (true, false, true, false);
midiEditorTimeViewport->setScrollBarsShown (false, false, false, true);
jimc
April 18, 2019, 7:45am
8
Well if it worked for you that’s good news I’ll go digging.
jimc
April 28, 2019, 3:34pm
9
I have no idea how this could have worked
It only works for me if I modify Viewport something like below. See the changed if statement on about line 10.
bool Viewport::useMouseWheelMoveIfNeeded (const MouseEvent& e, const MouseWheelDetails& wheel)
{
if (! (e.mods.isAltDown() || e.mods.isCtrlDown() || e.mods.isCommandDown()))
{
const bool canScrollVert = (allowScrollingWithoutScrollbarV || getVerticalScrollBar().isVisible());
const bool canScrollHorz = (allowScrollingWithoutScrollbarH || getHorizontalScrollBar().isVisible());
auto deltaX = rescaleMouseWheelDistance (wheel.deltaX, singleStepX);
auto deltaY = rescaleMouseWheelDistance (wheel.deltaY, singleStepY);
if (canScrollHorz && std::abs(deltaX) > 0 || canScrollVert && std::abs(deltaY) > 0) // < added test to see if scroll was horizontal or vertical
{
auto pos = getViewPosition();
if (deltaX != 0 && deltaY != 0 && canScrollHorz && canScrollVert)
{
pos.x -= deltaX;
pos.y -= deltaY;
}
else if (canScrollHorz && (deltaX != 0 || e.mods.isShiftDown() || ! canScrollVert))
{
pos.x -= deltaX != 0 ? deltaX : deltaY;
}
else if (canScrollVert && deltaY != 0)
{
pos.y -= deltaY;
}
if (pos != getViewPosition())
{
setViewPosition (pos);
return true;
}
}
}
return false;
}
But that doesn’t look like a great solution as it goes funny if I drag diagonally.
Maybe it’d be better to pass all mousewheel events to the parent viewport, but however I do it looks like I’ll need a custom Viewport class.
jimc
April 28, 2019, 3:36pm
10
This fixes it for me - looks like I’ll need a custom Viewport class.
void Viewport::mouseWheelMove (const MouseEvent& e, const MouseWheelDetails& wheel)
{
(void)useMouseWheelMoveIfNeeded (e, wheel);
Component::mouseWheelMove (e, wheel);
}
jimc
April 28, 2019, 3:37pm
11
This is only any use when you have nested viewports that scroll in different directions, otherwise the behaviour would be weird