As far as I know there’s not a simple way to get around this. It’d be useful to have an option to enable this behaviour though so I’ll take a look at tweaking the Viewport class a bit and let you know when it’s done.
I’ve added a fix for this on develop. There’s now a viewportIgnoreDragFlag member of the ComponentFlags struct in Component that you can set to indicate that a mouse drag event on it or any of its children should not move the Viewport that they are contained in if it has drag-to-scroll functionality enabled. So in your case you would do:
yourSlider.setViewportIgnoreDragFlag (true)
and the Viewport should not move when you are dragging the slider, however it will move when you drag on the empty background or any other Components that do not have this flag set.
This works in a basic use case but creates problems when using multi touch. Touching a slider with one finger and touching a non-blocking component with another creates buggy behaviour. I’d say if one finger blocks the viewport, all other fingers should be blocked, too.
Tested it quickly - works for my app - but haven’t tried multi-touch yet.
So really grateful to have a fix / work-around. Thanks Ed!!
But I think this should be the default behaviour, ie: the current behaviour of intercepting touches on child components is extremely unusual - no other event model I’ve used (iOS, Mac, Windows, Motif, X11) would behave like this. As it stands this solution means I have to write special code into my child components to disable weird behaviour in some parent view controller. This is clearly back to front, imagine you were using a closed-source 3rd party component library!
I have another question about the viewport class:
I’d like to have a rubber band effect on the edges, like on iOS. Is it possible to make the AnimatedPosition inside the viewport accessible?
I have a viewport with (homegrown) sliders inside, and noticed a (potential) lack of setScrollOnDragEnabled functionality:
When using it during a mouseDrag, it will be without effect because the DragToScrollListener’s “isViewportDragBlocked” is only set during mouseDown and mouseUp.
Adding isViewportDragBlocked = doesMouseEventComponentBlockViewportDrag(e.eventComponent);
at the beginning of its mouseDrag function.
This is useful when if you decide about scrolling depending i.e. on the first drag distance or timestamp.
Yes, that’s where I come from. Maybe I wasn’t clear…
(But… doesn’t it need to be true to block scrolling?)
I wanted to only scroll if the initial dragging speed is above a certain value. Otherwise the slider’s value is to be changed. So I call setViewportIgnoreDragFlag(true) in my mouseDrag() routine.
So here’s what I found out:
Actually it’s not the component’s viewportIgnoreDragFlag that keeps the Viewport from moving, but the DragToScrollListener::isViewportDragBlocked variable. It is set to doesMouseEventComponentBlockViewportDrag(e.eventComponent) (which sums up all components’ viewportIgnoreDragFlags) during mouse downs and ups - but not during drags, so it never became true. As a result, viewportIgnoreDragFlag can be true while the Viewport will move.
My fix works just fine and may be useful for others - but is located in juce code…:
add isViewportDragBlocked = doesMouseEventComponentBlockViewportDrag(e.eventComponent);
at the beginning of Viewport::DragToScrollListener::mouseDrag(), so isViewportDragBlocked gets set, just like it does in mouseDown() and mouseUp().
Well yes, that’s what you always could do, even in mouse up and down.
But then you need access to the Viewport from within the component - render this automatism useless, doesn’t it?
Other point multitouch:
When I release the component I’d need to re-enable touchScrolling, which would be bad if a second component is still “in use”
Or do I get something completely wrong?
So just for my understanding:
why is the flag only checked in mouse up and down, but not in drag?
Ah I see now. It makes sense to remove the check from mouseDown and mouseUp and only do it in mouseDrag as that’s the only place it gets used, which will also allow you to change it during a mouseDrag. I’ll add this to develop.
Also, yes I should have said
Have you tried setting the setViewportIgnoreDragFlag flag to true in your sliders as mentioned above?
in my previous post and I’ve edited it to correct that, sorry!