Scrollbar on the left...is it possible?


#1

Hi

I know this question was already asked previously, but since it’s been 4 years, maybe things changed in the meantime.
My question is very simple, is there an easy way to make the scrollbar of a viewport component to be on the left instead of the default right position?

Thanks

Nathaniel


#2

no, it’s hardcoded to the right :

verticalScrollBar.setBounds (contentArea.getWidth(), 0, scrollbarWidth, contentArea.getHeight());

#3

It might well have been my question you saw on this, 4 years ago. I solved it this way, in this case with a treeview.

This may not be very pretty but it worked then and I haven’t touched it since…
It most certainly is ugly, but, it saves you from forking juce’s viewport class.

Note that I also wanted stepped scrolling - not smooth, which this implements. The step size is in the cellSize variable.

(in constructor)

m_TreeView->setRootItem(m_RootItem);
m_TreeView->setMultiSelectEnabled (false);
m_TreeView->setIndentSize(0);
m_TreeView->setRootItemVisible(false);
m_TreeView->getViewport()->getViewedComponent()->addComponentListener(this);
m_TreeView->getViewport()->setScrollBarsShown(false, false);

addAndMakeVisible(m_TreeView);

m_TreeScrollBar = new ScrollBar(true);
addAndMakeVisible(m_TreeScrollBar);
m_TreeScrollBar->addListener(this);

(…)

And then further down:

void PresetListPanelBase::scrollBarMoved(    ScrollBar* scrollBarThatHasMoved, 
                                            double newRangeStart) {
    const int cellSize = this->r_Controller->getSettingsModel()->GetCellSize();
    const int newRangeStartInt = roundToInt(newRangeStart);

    int diff = newRangeStartInt%cellSize;
    int newRounded = newRangeStartInt-diff;
    int oldPos;

    if (scrollBarThatHasMoved == m_TreeScrollBar) {
        oldPos = m_TreeView->getViewport()->getViewPositionY();

        if( oldPos != newRounded) {
            m_TreeView->getViewport()->setViewPosition(
                m_TreeView->getViewport()->getViewPositionX(), 
                newRangeStartInt);
        }    

        if(diff != 0)
            m_TreeScrollBar->setCurrentRangeStart(newRounded);
    }
}

void PresetListPanelBase::componentMovedOrResized(    Component& component,  
                                                        bool /*wasMoved*/,
                                                        bool /*wasResized*/) {
    updateVisibleArea(&component);
}

void PresetListPanelBase::updateVisibleArea(Component* contentComp) {
    if ( m_TreeView->getViewport()->getViewedComponent() == contentComp ) {
        Rectangle<int> contentArea (m_TreeView->getLocalBounds());

        Rectangle<int> contentBounds;

        if (contentComp != nullptr)
            contentBounds = m_TreeView->getLocalArea(contentComp, contentComp->getLocalBounds());

        Point<int> visibleOrigin (-contentBounds.getPosition());

        double rangeLimit;

        if(contentBounds.getHeight()<=contentArea.getHeight())
            rangeLimit = contentArea.getHeight()+1;
        else
            rangeLimit = contentBounds.getHeight();

        m_TreeScrollBar->setRangeLimits (0.0, rangeLimit);
        m_TreeScrollBar->setCurrentRange (visibleOrigin.getY(), contentArea.getHeight());
    }
}

#4

yes it is your post I have seen 4 years ago

still I am not sure about the solution you propose, can you please precise what is a treeview, and where in the code you decide of the position of the scrollbar?

Thanks
Nathaniel


#5

You don’t need the treeview, it’s just a component that uses a viewport…

What @onar3d does is to disable the built in scrollbars of the viewport using void Viewport::setScrollBarsShown(…). Instead he creates a new instance of scrollbar which you can place in your resize method like any other component:

m_viewport()->setScrollBarsShown (false, false);
addAndMakeVisible (m_viewport);

m_scrollBar = new ScrollBar(true);
addAndMakeVisible(m_scrollBar);
m_scrollBar->addListener (this);

Unfortunately you cannot connect direcly to the viewport as listener, because that understands only it’s built in. But you can still get inspiration in the source code (or from onar3d’s post):

Now finally the placement left you do in the riesized() method, like you normally define the placement of your widgets:

void resized() override {
    const int w = getWidth();
    const int h = getHeight();
    const int sw = m_viewport->getScrollBarThickness();

    m_scrollBar->setBounds (0, 0, sw, h);
    m_viewport->setBounds (sw, 0, w-sw, h);
}

Hope that helps…