Bug report: SelectedItemSet sends unnecessary change messages

There is a subtle bug in SelectedItemSet::operator= which results in the unwanted behavior that when you select items from right-to-left or down-to-up, the change message is sent for every mouse movement, regardless of whether or not the selection was changed. Selecting from left-to-right or up-to-down filters out the unchanged selections as intended.

To see this, run the following code, which implements lasso selection in the simplest possible way. Select the bottom row of cells left-to-right and then right-to-left and look at the debug window.

class MainComponent : public juce::Component,
                      public juce::LassoSource<juce::TextButton*>,
                      public juce::ChangeListener
{
public:

    MainComponent()
    {
        addChildComponent(lasso);
        setSize(400, 400);
        selectedItems.addChangeListener(this);

        for (int x = 1; x < 5; ++x)
        {
            for (int y = 1; y < 5; ++y)
            {
                auto s = components.add(new juce::TextButton());
                s->setBounds({ x * 40, y * 40, 30, 30 });
                addAndMakeVisible(s);
            }
        }

    }

    void findLassoItemsInArea(juce::Array<juce::TextButton*>& itemsFound, const juce::Rectangle<int>& area) override
    {
        for (auto c : components)
        {
            if (c->getBoundsInParent().intersects(area))
                itemsFound.add(c);
        }
    }


    juce::SelectedItemSet<juce::TextButton*>& getLassoSelection() override { return selectedItems; }

    void changeListenerCallback(juce::ChangeBroadcaster*) override
    {
        static int i = 0;
        DBG("selection changed " << i++);
    }

    void mouseDown(const juce::MouseEvent& m) override
    {
        lasso.beginLasso(m, this);
    }

    void mouseDrag(const juce::MouseEvent& m) override
    {
        lasso.dragLasso(m);
    }

    void mouseUp(const juce::MouseEvent& m) override
    {
        lasso.endLasso();
    }

private:
    juce::OwnedArray<juce::TextButton> components;
    juce::SelectedItemSet<juce::TextButton*> selectedItems;
    juce::LassoComponent<juce::TextButton*> lasso;
};

The problem seems to be as follows: the second for-loop inside SelectedItemSet::operator= results in the internal selectedItems and the incoming other arrays being sorted differently. Then on the next turn, the first line selectedItems != other.selectedItems returns as false.

In this case, the behavior is triggered by the logic inside my findLassoItemsInArea() function, which always sorts the array left-to-right, top-to-bottom, regardless of which way the lasso is pulled. The bug could be fixed by sorting the array differently there. But this is an unnecessary burden for the user, and the problem would be much better addressed inside the SelectedItemSet class. I would suggest that simply copying (or moving) the incoming other.selectedItems over and then dealing with the selection / deselection logic separately would be the best thing to do.