ListBox::selectedRowsChanged() request (isMouseClick)

Hi Jules,

I’ve got a TableListBox where I need to know if the selection has changed with a mouse click or via the Up/Down keys…. so I was wondering if you would consider changing (or adding):

//==============================================================================
    /** Override this to be informed when rows are selected or deselected.
        @see ListBox::selectedRowsChanged()
    */
    virtual void selectedRowsChanged (int lastRowSelected);

to

//==============================================================================
    /** Override this to be informed when rows are selected or deselected.
        @see ListBox::selectedRowsChanged()
    */
    virtual void selectedRowsChanged (int lastRowSelected, bool isMouseClick);

and in Listbox::selectRowInternal() change the call to:

void ListBox::selectRowInternal (const int row,
                                 bool dontScroll,
                                 bool deselectOthersFirst,
                                 bool isMouseClick)
{
    if (! multipleSelection)
        deselectOthersFirst = true;

    if ((! isRowSelected (row))
         || (deselectOthersFirst && getNumSelectedRows() > 1))
    {
        if (isPositiveAndBelow (row, totalItems))
        {
            if (deselectOthersFirst)
                selected.clear();

            selected.addRange (Range<int> (row, row + 1));

            if (getHeight() == 0 || getWidth() == 0)
                dontScroll = true;

            viewport->selectRow (row, getRowHeight(), dontScroll,
                                 lastRowSelected, totalItems, isMouseClick);

            lastRowSelected = row;
            model->selectedRowsChanged (row, isMouseClick);
        }
        else
        {
            if (deselectOthersFirst)
                deselectAllRows();
        }
    }
}

BTW - I know we have cellClicked() but it’s called after selectedRowsChanged() - so I can do what I want using a private boolean value which I set in selectedRowsChanged() and check for in cellClicked()… but it would be cleaner with the above change.

Thanks,

Rail

So dealing with the edge cases between a mouse click and keyboard selection changed was much easier dealt with by adding:

void ListBoxModel::selectedRowsChanged (int lastRowSelected, bool /* isMouseClick */) { selectedRowsChanged (lastRowSelected); }

around line 963 in juce_ListBox.cpp and changing line 511 to

model->selectedRowsChanged (row, isMouseClick);

And also add the definition in the juce_ListBox.h header

virtual void selectedRowsChanged (int lastRowSelected, bool isMouseClick);

Rail

There will be hundreds of people out there with code that would break if I changed this, so I'm not really keen to do it! Couldn't you cheat and just check whether the mouse button is down at the time when the selection happens?

I’ll check if that’ll work – but my suggestion above in post 2 will not affect any existing code.

It adds a new overloaded member function and the default implementation calls the original (I tested for that to make sure it was a safe change).

Thanks,

Rail

See my post #6

Thanks,

Rail

I take that back…

void CGroupTable::selectedRowsChanged (int iNewRow)
{
    bool isMouseClick = isMouseButtonDown();
    :
}

isMouseButtonDown () doesn’t always return true when making a selection with the mouse.

My changes in post #2 above work 100% and are backward compatible.

void CGroupTable::selectedRowsChanged (int iNewRow, bool isMouseClick)
{
    bool bTemp = isMouseButtonDown();
    
    DBG ("isMouseButtonDown: " + String (bTemp) + ", isMouseClick: " + String (isMouseClick));

logs:

As you can see using isMouseButtonDown() is unreliable.

Thanks,

Rail

Yes, obviously your suggestion would work, but like I said, it'd be a breaking change that would impact hundreds/thousands of projects, which is why I'm reluctant to do it!

Also it doesn't feel right to me for it to matter what the cause of the selection change was.. I can't really imagine a situation where I'd write code where that would be right way to do it. What's your actual use-case for this?

Hi Jules,

I sent you a PM with a video showing the use-case.

I still think the overloaded method I posted in post #2 should not break existing code.

Cheers,

Rail