Vertical scroll to parent

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?

Is this a hard question or just incomprehensible? :slight_smile:

Do you have the correct setScrollBarsShown config for each Viewport?

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…

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);

Well if it worked for you that’s good news :slight_smile: I’ll go digging.

I have no idea how this could have worked :slight_smile:

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.

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);
}

This is only any use when you have nested viewports that scroll in different directions, otherwise the behaviour would be weird :slight_smile: