Think about to use TextEditor in TableListBox


#1

Hi there,

I’m now trying to use Label/TextEditor in the TableListBox as editable cell.

We can use TableListBoxModel::refreshComponentForCell() to use our desired component instead of its internal cell component.

When I put a label component as a cell, it intercepts mouse click so the it can’t be used for row selection by user mouse click.

Next I thought that create a temporary text editor when the cell is clicked. But there are no way to get the cell component which can be used as parent of text editor.

I’d like to make editable list view like iTunes, what is the good way to do?

Best regards,
Masanao Hayashi


#2

you could try adding the TableListBox as a mouse listener for your cell component - doing so passes on all mouse events to the listener component also. The only thing that might cause this to not work is if the TableListBox’s mouse functions check the originating component in the event - i just checked the code and it doesn’t, so you should be okay.

If that causes odd behaviour for you, the only real alternative is to give your cell components the ability to call a row selection function in the actual TableListBox when it is clicked [you could use findParentComponentOfClass()], but tbh i think you’ll be okay with a mouselistener.


#3

No, I want TableListBox to receive mouse events.

Thanks! findParentComponentOfClass() is the one of feature what I need. I don’t have to pass the pointer of the TableListBox any longer. :smiley:

In fact, I’m doing this approach, it’s very complicated. As you wrote, the cell component must know the parent TableListBox and row/column information. Then the component calls some methods of TableListBox when mouse clicked…

The code below is simple case, cell component consists of just only a label. But when the component is more complicated (i.e. component which includes a label to show the name and a button to search…), it should be more complicated…

//******************************************************************************
//	CListItemLabel.h
//******************************************************************************
#ifndef	__CListItemLabel_h__
#define __CListItemLabel_h__


#include "juce.h"


//==============================================================================
//	CListItemLabel
//==============================================================================
class CListItemLabel :
	public Label,
	public Timer
{
public:
	CListItemLabel(TableListBox* pOwner, const String& sLabelText = String::empty);

	//	Label overrides.
	virtual void mouseMove(const MouseEvent& e);
	virtual void mouseExit(const MouseEvent& e);
	virtual void mouseDown(const MouseEvent& e);
	virtual void mouseDrag(const MouseEvent& e);
	virtual void mouseUp(const MouseEvent& e);
protected:
	virtual void mouseDoubleClick(const MouseEvent& e);
public:
	virtual void textEditorReturnKeyPressed(TextEditor& ed);
	virtual void textEditorEscapeKeyPressed(TextEditor& ed);
	virtual void paint(Graphics& g);

	//	Timer overrides.
	virtual void timerCallback();

	int GetRow() const { return m_iRow; }
	void SetRow(const int iRow) { m_iRow = iRow; }
	int GetColumnId() const { return m_iColumnId; }
	void SetColumnId(const int iColumnId) { m_iColumnId = iColumnId; }
	void SetRowAndColumnId(const int iRow, const int iColumnId) { SetRow(iRow); SetColumnId(iColumnId); }

	void CreateEditor();
	void CleanupEditor();
	void EnableClickEdit(bool bEnabled = true) { m_bEnableClickEdit = bEnabled; }
	
	TableListBox* GetOwner() const { return m_pOwner; }

	void SetSelected(const bool bSelected = true) { if (m_bSelected != bSelected) m_bSelected = bSelected; }
	bool IsSelected() const { return m_bSelected; }

	void SetDrawLineEnabled(bool bShouldBeEnabled = true) { m_bDrawLineEnabled = bShouldBeEnabled; }
	bool IsDrawLineEnabled() const { return m_bDrawLineEnabled; }

private:
	TableListBox* m_pOwner;
	int		m_iRow;
	int		m_iColumnId;
	bool	m_bClickedtoEdit;
	int		m_iMouseDownX;
	int		m_iMouseDownY;
	bool	m_bEnableClickEdit;
	bool	m_bSelected;
	bool	m_bDrawLineEnabled;
};
#endif	//	!__CListItemLabel_h__

//******************************************************************************
//	CListItemLabel.cpp
//******************************************************************************
#define __CListItemLabel_cpp__


#include "CListItemLabel.h"


//==============================================================================
//	CListItemLabel
//==============================================================================
//------------------------------------------------------------------------------
//	Constructor
//------------------------------------------------------------------------------
CListItemLabel::CListItemLabel(TableListBox* pOwner, const String& sLabelText) :
	Label(T("CListItemLabel"), sLabelText),
	m_pOwner(pOwner),
	m_iRow(-1),
	m_iColumnId(-1),
	m_bClickedtoEdit(false),
	m_bEnableClickEdit(false),
	m_bSelected(false),
	m_bDrawLineEnabled(true)
{
}


//------------------------------------------------------------------------------
//	mouseMove
//------------------------------------------------------------------------------
void CListItemLabel::mouseMove(const MouseEvent& e)
{
	if (isTimerRunning()) {
		if ((abs(e.x - m_iMouseDownX) > 10) || (abs(e.x - m_iMouseDownX) > 10))
			CreateEditor();
	}

	Component* pComponent = getParentComponent();
	if (pComponent != NULL) {
		MouseEvent mEvent = e.getEventRelativeTo(pComponent);
		pComponent->mouseMove(mEvent);
	}
	Label::mouseMove(e);
}


//------------------------------------------------------------------------------
//	mouseExit
//------------------------------------------------------------------------------
void CListItemLabel::mouseExit(const MouseEvent& e)
{
	if (isTimerRunning())
		CreateEditor();
	Label::mouseExit(e);
}


//------------------------------------------------------------------------------
//	mouseDown
//------------------------------------------------------------------------------
void CListItemLabel::mouseDown(const MouseEvent& e)
{
	m_bClickedtoEdit = false;
	if (e.mods.isLeftButtonDown() &&
		(!e.mods.isAnyModifierKeyDown()) &&
		(e.getNumberOfClicks() == 1)) {

		int iLength = getFont().getStringWidth(getText()) + 3;
		if (iLength < 8)
			iLength = 8;
		if (e.x < iLength) {
			SparseSet<int> aiSelectedRows = m_pOwner->getSelectedRows();
			if ((aiSelectedRows.size() == 1) && (aiSelectedRows[0] == GetRow())) {
				m_bClickedtoEdit = m_bEnableClickEdit;
				m_iMouseDownX = e.x;
				m_iMouseDownY = e.y;
			}
		}
	}

	Component* pComponent = getParentComponent();
	if (pComponent != NULL) {
		MouseEvent mEvent = e.getEventRelativeTo(pComponent);
		pComponent->mouseDown(mEvent);
	}
//	Label::mouseDown(e);
}


//------------------------------------------------------------------------------
//	mouseDrag
//------------------------------------------------------------------------------
void CListItemLabel::mouseDrag(const MouseEvent& e)
{
	Component* pComponent = getParentComponent();
	if (pComponent != NULL) {
		MouseEvent mEvent = e.getEventRelativeTo(pComponent);
		pComponent->mouseDrag(mEvent);
	}
//	Label::mouseDrag(e);
}


//------------------------------------------------------------------------------
//	mouseUp
//------------------------------------------------------------------------------
void CListItemLabel::mouseUp(const MouseEvent& e)
{
	if (m_bClickedtoEdit) {
		m_bClickedtoEdit = false;
		startTimer(500);
	}

	Component* pComponent = getParentComponent();
	if (pComponent != NULL) {
		MouseEvent mEvent = e.getEventRelativeTo(pComponent);
		pComponent->mouseUp(mEvent);
	}
//	Label::mouseUp(e);
}


//------------------------------------------------------------------------------
//	mouseDoubleClick
//------------------------------------------------------------------------------
void CListItemLabel::mouseDoubleClick(const MouseEvent& e)
{
	Label::mouseDoubleClick(e);
	if (isTimerRunning())
		stopTimer();

	Component* pComponent = getParentComponent();
	if (pComponent != NULL) {
		MouseEvent mEvent = e.getEventRelativeTo(pComponent);
		pComponent->mouseDoubleClick(mEvent);
	}
}


//------------------------------------------------------------------------------
//	textEditorReturnKeyPressed
//------------------------------------------------------------------------------
void CListItemLabel::textEditorReturnKeyPressed(TextEditor& ed)
{
	Label::textEditorReturnKeyPressed(ed);
	CleanupEditor();
}


//------------------------------------------------------------------------------
//	textEditorEscapeKeyPressed
//------------------------------------------------------------------------------
void CListItemLabel::textEditorEscapeKeyPressed(TextEditor& ed)
{
	Label::textEditorEscapeKeyPressed(ed);
	CleanupEditor();
}


//------------------------------------------------------------------------------
//	timerCallback
//------------------------------------------------------------------------------
void CListItemLabel::timerCallback()
{
	CreateEditor();
}


//------------------------------------------------------------------------------
//	paint
//------------------------------------------------------------------------------
void CListItemLabel::paint(Graphics& g)
{
	if (!isEditable()) {
		Colour mTextColour = (m_pOwner->hasKeyboardFocus(true) && IsSelected())?
			Colours::white: Colours::black;
		setColour(Label::textColourId, mTextColour);
	}

	Label::paint(g);

	if (IsDrawLineEnabled()) {
		g.setColour(Colour(LIST_ROW_COLOUR_RULE));
		g.drawLine((float)(getWidth() - 1), 0, (float)(getWidth() - 1), (float)getHeight());
	}
}


//------------------------------------------------------------------------------
//	CreateEditor
//------------------------------------------------------------------------------
void CListItemLabel::CreateEditor()
{
	if (isTimerRunning())
		stopTimer();
	showEditor();
	setColour(Label::backgroundColourId,	Colours::white);
	setColour(Label::textColourId,			Colours::black);
}


//------------------------------------------------------------------------------
//	CleanupEditor
//------------------------------------------------------------------------------
void CListItemLabel::CleanupEditor()
{
	if (!isEditable()) {
		setColour(Label::backgroundColourId,	Colour(0x00000000));
		setColour(Label::textColourId,			Colours::black);
	}
}