ListBox Drag-To-Reorder [Solved]


#1

I’m trying to figure out how to get Drag-To-Reorder working with the ListBox class.
Here’s what I’m doing:
MainComponent.h

#ifndef MAINCOMPONENT_H_INCLUDED
#define MAINCOMPONENT_H_INCLUDED

#include "../JuceLibraryCode/JuceHeader.h"

struct ListBoxItem : public Component, public DragAndDropTarget
{
    ListBoxItem(int id) : idNum(id)
    {
        Random r;
        Colour _c((uint8)r.nextInt({50,255}),
                 (uint8)r.nextInt({50,255}),
                 (uint8)r.nextInt({50,255}));
        c = _c;
        setInterceptsMouseClicks(false, false);
    }

    ListBoxItem(const ListBoxItem& other)
    {
        c = other.c;
        idNum = other.idNum;
        setInterceptsMouseClicks(false, false);
    }

    void paint(Graphics& g) override
    {
        g.fillAll(c);
        g.setColour(Colours::black);
        g.drawText(String(idNum), getLocalBounds(), Justification::centred);
    }
    bool isInterestedInDragSource (const SourceDetails &dragSourceDetails) override
    {
        return true;
    }

    void itemDragEnter (const SourceDetails &dragSourceDetails) override
    {
        DBG( "itemDragEnter" );
    }
    void itemDragMove (const SourceDetails &dragSourceDetails) override
    {
        DBG( "itemDragMove" );
    }
    void itemDragExit (const SourceDetails &dragSourceDetails) override
    {
        DBG( "itemDragExit" );
    }
    void itemDropped (const SourceDetails &dragSourceDetails) override
    {
        DBG( "item dropped: " << dragSourceDetails.description.toString() );
    }
    bool shouldDrawDragImageWhenOver () override
    {
        return true;
    }
    int idNum;
    Colour c;
};

struct Rules : public ListBoxModel
{
    int getNumRows() override
    {
        return items.size();
    }
    void paintListBoxItem(int rowNumber,
                          Graphics &g,
                          int width,
                          int height,
                          bool rowIsSelected) override
    {
    }
    var getDragSourceDescription (const SparseSet< int > &rowsToDescribe) override
    {
        return "Rules";
    }
    Component* refreshComponentForRow (int rowNumber,
                                       bool isRowSelected,
                                       Component *existingComponentToUpdate) override
    {
        //ScopedPointer<Component> toBeDeleted(existingComponentToUpdate);
        if( rowNumber < items.size() )
        {
            return &items[rowNumber];
        }
        return nullptr;
    }
    std::vector< ListBoxItem > items
    {
        {0},{1},{2},{3}
    };
};

struct ListBoxContainer : public Component, public DragAndDropContainer
{
    ListBoxContainer()
    {
        listBox.setModel(&rules);
        addAndMakeVisible(listBox);
    }
    void paint(Graphics& g) override
    {
        g.fillAll(Colours::white);
        g.setColour(Colours::red);
        g.drawRect(getLocalBounds());
    }
    void resized() override
    {
        listBox.setBounds(getLocalBounds().reduced(2) );
    }
    void dragOperationStarted (const DragAndDropTarget::SourceDetails &details) override
    {
        DBG("dragOperationStarted " << details.description.toString() );
    }
    void dragOperationEnded (const DragAndDropTarget::SourceDetails &details) override
    {
        DBG("dragOperationEnded " << details.description.toString() );
    }
    Rules rules;
    ListBox listBox;
};

//==============================================================================
/*
    This component lives inside our window, and this is where you should put all
    your controls and content.
*/
class MainContentComponent   : public Component
{
public:
    //==============================================================================
    MainContentComponent();
    ~MainContentComponent();

    void paint (Graphics&) override;
    void resized() override;

private:
    ListBoxContainer listBoxContainer;
    //==============================================================================
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainContentComponent)
};


#endif  // MAINCOMPONENT_H_INCLUDED

and the MainComponent.cpp:

#include "MainComponent.h"


//==============================================================================
MainContentComponent::MainContentComponent()
{
    addAndMakeVisible(listBoxContainer);
    setSize (600, 400);
}

MainContentComponent::~MainContentComponent()
{
}

void MainContentComponent::paint (Graphics& g)
{
    g.fillAll (Colour (0xff001F36));

    g.setFont (Font (16.0f));
    g.setColour (Colours::white);
    g.drawText ("Hello World!", getLocalBounds(), Justification::centred, true);
}

void MainContentComponent::resized()
{
    // This is called when the MainContentComponent is resized.
    // If you add any child components, this is where you should
    // update their positions.
    listBoxContainer.setBounds(20, 20, 100, 100);
}

When I drag one of the list box items, none of the DBG messages appear. What’s the problem? Shown here dragging item #1 and the DBG output that appears…


#3

Ok, this is solved. Here’s a git repo for anyone that wants to see the solution for ‘Drag-To-Reorder’ your list box. Helpful people were @'d in the code


Clearing custom components in TableListBox