[ListBox] and its custom [Component]'s mouse event


#1

Hi and Hello

I came to the point when im in need of a list that contains set of editable [Label] components.

[ListBox] was a natural choice here as i need to utilize its features. Unfortunatelly i cannot due to the nature of how [MouseEvent]'s are consumed.

Im rather aware of [MouseListener] approach but that doesnt seem to make the job ether.

I desire of a [ListBox]'es events to be active (receivable) with possibility of editing [Label] components that it contains as well.

I wonder if this is achievable in any non over convoluted way.
My first doubt was that the ListBox::mouseUp() method receives wrong coordinates, but its just assumpltion.

Does anyone tried similar scenario ?


class List : public Component, public ListBoxModel {
public:
	List() {
		box.setModel(this);
		box.setColour(ListBox::backgroundColourId, Colour::greyLevel(0.2f));
		box.setRowHeight(30);
		addAndMakeVisible(box);
	}

	void resized() override {
		box.setBounds(getLocalBounds());
	}

	void paintListBoxItem(int rowNumber, Graphics &g, int width, int height, bool rowIsSelected) override {
		if(!isPositiveAndBelow(rowNumber, names.size())) return;
		g.fillAll(Colour::greyLevel(rowIsSelected ? 0.15f : 0.05f));
	}

	int getNumRows() override {
		return names.size();
	}

	Component* refreshComponentForRow(int row, bool selected, Component* component) override {
		auto *item = static_cast<Item*>(component);
		if(row < names.size()) {
			if(!item)
				item = new Item(box, names);
			item->update(row, names[row]);
		} else {
			delete component;
			item = nullptr;
		}
		return item;
	}

	void addItem(const String &name = String("new item")) {
		names.add(name);
		box.updateContent();
	}

	void listBoxItemClicked(int row, const MouseEvent &) { // NOT CALLED !!!!
		DBG("selected row : " + String(row));
	}

private:
	ListBox box;
	StringArray names;
}

class MainComponent : public Component {
public:
	MainComponent() {
		addAndMakeVisible(list);

		for(int i = 0; i < 7; i++)
			list.addItem("item" + String(i));

		setSize(600, 400);
	}

	void paint(Graphics& g) override {
		g.fillAll(Colours::whitesmoke);
	}

	void resized() override {
		list.setBounds(0, 0, 110, getHeight());
	}

private:
	List list;

	JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MainComponent)
};

#2

Check out the TableListBox in the JUCE Demo project

Rail


#3

Ah, of course, my bad I’ve ignored that example … thank you Rail !


void mouseDown (const MouseEvent& event) override {
    // single click on the label should simply select the row
    owner.table.selectRowsBasedOnModifierKeys (row, event.mods, false);
    Label::mouseDown (event);
}

#4

Could this tiny example please be added to the refreshComponent* documentation for ListBox and TableListBox please!