stick
April 26, 2007, 10:04am
1
Hi !
I’m trying to manage id3 tags directly from my tableListBox component which displays my songs library (like iTunes does for example).
I’m overriding the refreshComponentForCell method to create a custom TextEditor which allows to modify the existing tag when any cell is clicked.
I would like to launch my saveTag() method whenever another cell is clicked than the currently focused.
Is there any existing virtual method called when my custom component loses focus and before it gets deleted ?
(focusgained is never called because the component has already been deleted)
I hope my poor english is clear enough for you to help me …
thanks in advance !
jules
April 26, 2007, 10:32am
2
Yes - check out the Label component, it has lots of methods for handling exactly this kind of thing.
stick
April 27, 2007, 8:17am
3
allright I hadn’t seen Label were editable, that’s exactly what I’m looking for…
thanks a lot
ring2
September 13, 2007, 5:51am
4
I did the similar thing like this,
if (columnId == kColumnIdName) {
String sLabelText = pXml->getStringAttribute(T("Name"));
Label* pLabel = (Label*)existingComponentToUpdate;
if (pLabel != NULL)
pLabel->setText(sLabelText, false);
else
pLabel = new Label(String::empty, sLabelText);
return pLabel;
}
else {
// for any other column, just return 0, as we'll be painting these columns directly.
jassert(existingComponentToUpdate == NULL);
return NULL;
}
I could get the name displayed in the label. But when I click the name column, the label component steals the mouse click and the line could not be selected.
What do you think about the good solution if I want the behavior like iTunes, Mac OS X Finder or Windows Explorer?
Masanao Hayashi
jules
September 13, 2007, 8:03am
5
You could use setEditable to only make the label editable on a double-click?
ring2
September 18, 2007, 1:11am
6
In the general application such as Finder, Explorer and iTunes, double click is not the way to edit the name.
The first click is selecting the row.
Click the selected row and wait 0.5 sec, the label is turned to be edited.
Click the selected row and move mouse immediately, the label is turned to be edited.
I want to implement those functions. Now I’m trying to make custom compnent which inherits Label but the code wil be complex…
Masanao Hayashi
ring2
September 19, 2007, 12:27pm
7
After some trying, here is my current solution…
Use this component in TableListBoxModel::refreshComponentForCell() to make the TableListBox like iTunes.
//******************************************************************************
// 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() { return m_iRow; }
void SetRow(int iRow) { m_iRow = iRow; }
int GetColumnId() { return m_iColumnId; }
void SetColumnId(int iColumnId) { m_iColumnId = iColumnId; }
void SetRowAndColumnId(int iRow, int iColumnId) { SetRow(iRow); SetColumnId(iColumnId); }
void CreateEditor();
void CleanupEditor();
private:
TableListBox* m_pOwner;
int m_iRow;
int m_iColumnId;
bool m_bClickedtoEdit;
int m_iMouseDownX;
int m_iMouseDownY;
};
#endif // !__CListItemLabel_h__
//******************************************************************************
// CListItemLabel.cpp
//******************************************************************************
#define __CListItemLabel_cpp__
#include "CListItemLabel.h"
CListItemLabel::CListItemLabel(TableListBox* pOwner, const String& sLabelText) :
Label(T("CListItemLabel"), sLabelText),
m_pOwner(pOwner),
m_iRow(-1),
m_iColumnId(-1),
m_bClickedtoEdit(false)
{
}
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);
}
void CListItemLabel::mouseExit(const MouseEvent& e)
{
if (isTimerRunning())
CreateEditor();
Label::mouseExit(e);
}
void CListItemLabel::mouseDown(const MouseEvent& e)
{
m_bClickedtoEdit = false;
if (e.mods.isLeftButtonDown() &&
(!e.mods.isAnyModifierKeyDown()) &&
(e.getNumberOfClicks() == 1)) {
SparseSet<int> aiSelectedRows = m_pOwner->getSelectedRows();
if ((aiSelectedRows.size() == 1) && (aiSelectedRows[0] == GetRow())) {
m_bClickedtoEdit = true;
m_iMouseDownX = e.x;
m_iMouseDownY = e.y;
}
else {
aiSelectedRows.clear();
aiSelectedRows.addRange(GetRow(), 1);
m_pOwner->setSelectedRows(aiSelectedRows);
}
}
Component* pComponent = getParentComponent();
if (pComponent != NULL) {
MouseEvent mEvent = e.getEventRelativeTo(pComponent);
pComponent->mouseDown(mEvent);
}
// Label::mouseDown(e);
}
void CListItemLabel::mouseDrag(const MouseEvent& e)
{
Component* pComponent = getParentComponent();
if (pComponent != NULL) {
MouseEvent mEvent = e.getEventRelativeTo(pComponent);
pComponent->mouseDrag(mEvent);
}
// Label::mouseDrag(e);
}
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);
}
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);
}
}
void CListItemLabel::textEditorReturnKeyPressed(TextEditor& ed)
{
Label::textEditorReturnKeyPressed(ed);
CleanupEditor();
}
void CListItemLabel::textEditorEscapeKeyPressed(TextEditor& ed)
{
Label::textEditorEscapeKeyPressed(ed);
CleanupEditor();
}
void CListItemLabel::timerCallback()
{
CreateEditor();
}
void CListItemLabel::paint(Graphics& g)
{
if (!isEditable()) {
Colour mTextColour = (m_pOwner->hasKeyboardFocus(true) && m_pOwner->isRowSelected(GetRow()))?
Colours::white: Colours::black;
setColour(Label::textColourId, mTextColour);
}
Label::paint(g);
g.setColour(Colour(0x30000000));
g.drawLine((float)(getWidth() - 1), 0, (float)(getWidth() - 1), (float)getHeight());
}
void CListItemLabel::CreateEditor()
{
if (isTimerRunning())
stopTimer();
showEditor();
setColour(Label::backgroundColourId, Colours::white);
setColour(Label::textColourId, Colours::black);
}
void CListItemLabel::CleanupEditor()
{
if (!isEditable()) {
setColour(Label::backgroundColourId, Colour(0x00000000));
setColour(Label::textColourId, Colours::black);
}
}