scrollBarMoved in Viewport not firing final coordinates after 'swiping'

gui

#1

Hey guys, I’ve been trying to get to the scrollbar component being used in my viewport through the use of the scrollBarMoved listener. MouseWheelMoved isn’t enough for me in this case

class InstrumentList : public Viewport
{
public:
InstrumentList()
{
	
	child.setSize(600, 600);
	view.setViewedComponent(&child, false);
	view.setScrollOnDragEnabled(true);

    //view.addListener(this); not valid code
	view.addMouseListener(this, true);
	addAndMakeVisible(view);

}

void paint(Graphics& g) 
{

}

void resized() override
{
	view.setBounds(0, 0, 500, 500);
}

void mouseWheelMove(const MouseEvent &event, const MouseWheelDetails &wheel) override {
	// can get to work using .addMouseListener(this)
}

void scrollBarMoved(ScrollBar *, double newRangeStart) override {
	// cannot get to work because .addListener is not an option for my declared view element
}

private:
	SomeComponent child;
	Viewport view;
	//==============================================================================
	JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(InstrumentList)
};

I guess I am wondering mostly why ‘.addListener’ alone isn’t included in Viewport and how else I can access the scrollBarMoved member function in a manner like above?

EDIT: See below post for updated title topic


#2

ScrollBar& Viewport::getHorizontalScrollBar	(		)	

and
https://docs.juce.com/master/classScrollBar_1_1Listener.html

struct Foo : public ScrollBar::Listener
{
    Foo() { view.getHorizontalScrollBar.addListener(this); }
    void scrollBarMoved (ScrollBar *scrollBarThatHasMoved, double newRangeStart) override {}

    Viewport view;
};

#3

Cool this got me straightened back out, I was incorrectly using Viewport as a subclass rather just Component when I tried your way earlier which causes errors.


#4

Okay so trying not to make a new thread, but I’ve run into another issue for scroll bar position. Updating the code to a correct version we have:

class InstrumentList : public Component
{
public:
InstrumentList()
{
	
	child.setSize(600, 600);
	view.setViewedComponent(&child, false);
	view.setScrollOnDragEnabled(true);
	view.addMouseListener(this, true);
	scroll = &view.getVerticalScrollBar();
    scroll.addListener(this)
	scrollBarPos = scroll->getCurrentRange().getStart();

	addAndMakeVisible(view);

}

void paint(Graphics& g) 
{

}

void resized() override
{
	view.setBounds(0, 0, 600, 100);
}

void mouseDrag(const MouseEvent &event) override {
	scrollBarPos = scroll->getCurrentRange().getStart();
}

void mouseWheelMove(const MouseEvent &event, const MouseWheelDetails &wheel) override {
	scrollBarPos = scroll->getCurrentRange().getStart();
}

void scrollBarMoved(ScrollBar *, double newRangeStart) override {
	scrollBarPos = scroll->getCurrentRange().getStart();
}

private:
	SomeComponent child;
	Viewport view;
	double scrollBarPos;
    ScrollBar *scroll;
    //==============================================================================
        	JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(InstrumentList)
    };

and unfortunately none of those 3 listeners fire accurately after drag and releasing the viewport. When I say ‘drag and release’ I am referring to the extra movement we see when scrolling after sliding a finger very fast across the screen. The best I can get is through a mouseDown listener, but it stops updating and providing me with a trigger to check my scrollBar’s position after I lift my finger/mouse. scrollBarMoved I assume should handle these extra movements but don’t appear to do so.


#5

what is scroll ?


#6

Sorry, scroll is a pointer to a ScrollBar instantiated to the current viewport’s vertical scrollbar, I have updated my code to show its declaration!


#7

Why not take a reference?

class InstrumentList : public Component
{
public:
InstrumentList() : scroll( view.getVerticalScrollbar() )
{
	
	child.setSize(600, 600);
	view.setViewedComponent(&child, false);
	view.setScrollOnDragEnabled(true);
	view.addMouseListener(this, true);
    scroll.addListener(this);
	scrollBarPos = scroll.getCurrentRange().getStart();

	addAndMakeVisible(view);

}

	Viewport view;  //must be initialized before ScrollBar& member
	double scrollBarPos;
    ScrollBar& scroll;

also, scrollbar listener has its own set of callbacks, separate from those mouseListener callbacks. so, be sure to implement those if you’re listening to the scrollbar:
https://docs.juce.com/master/classScrollBar_1_1Listener.html


#8

That is much more readable thanks! After making those changes I still have the same problem, the ScrollBar Listener class only has 1 function which is the scrollBarMoved(). ScrollBarMoved seems to only be called by direct by mouse interactions inside the scroll bar’s vertical wrapper. Without the mouseDrag & mouseWheelMove listeners, I cannot update scrolling which takes place inside the viewport. However with these three together, I can almost keep up with the actual scroll bar’s position, except for when I swipe and release, the scroll bar rolls with momentum for a bit and I cannot keep up with its position.


#9

you never said why you needed to keep track of that variable. the Viewport is supposed to be pretty self-contained. you don’t need to do anything but pass in a Component that it should display. Why are you trying to track the viewed position via some approach other than

virtual void Viewport::visibleAreaChanged( const Rectangle< int > & newVisibleArea)

?

just override that if you want the bounding box of what is displayed in your component inside the viewport


#10

I was using it to determine the values needed for certain entrance and departure position changes happening to the components as they exit the viewport. It seems using the visibleAreaChanged listener feedbacks correctly on swipes so case closed, much appreciated!


#11

Awesome, glad to hear that turned out to be a viable solution