+//-----------------------------------------------------------------------------
+// wxListCtrlRenameTimer (internal)
+//-----------------------------------------------------------------------------
+
+class wxListCtrlRenameTimer: public wxTimer
+{
+private:
+ wxListCtrl *m_owner;
+
+public:
+ wxListCtrlRenameTimer( wxListCtrl *owner );
+ void Notify();
+};
+
+//-----------------------------------------------------------------------------
+// wxListCtrlTextCtrlWrapper: wraps a wxTextCtrl to make it work for inline editing
+//-----------------------------------------------------------------------------
+
+class wxListCtrlTextCtrlWrapper : public wxEvtHandler
+{
+public:
+ // NB: text must be a valid object but not Create()d yet
+ wxListCtrlTextCtrlWrapper(wxListCtrl *owner,
+ wxTextCtrl *text,
+ long itemEdit);
+
+ wxTextCtrl *GetText() const { return m_text; }
+
+ void AcceptChangesAndFinish();
+
+protected:
+ void OnChar( wxKeyEvent &event );
+ void OnKeyUp( wxKeyEvent &event );
+ void OnKillFocus( wxFocusEvent &event );
+
+ bool AcceptChanges();
+ void Finish();
+
+private:
+ wxListCtrl *m_owner;
+ wxTextCtrl *m_text;
+ wxString m_startValue;
+ long m_itemEdited;
+ bool m_finished;
+ bool m_aboutToFinish;
+
+ DECLARE_EVENT_TABLE()
+};
+
+//-----------------------------------------------------------------------------
+// wxListCtrlRenameTimer (internal)
+//-----------------------------------------------------------------------------
+
+wxListCtrlRenameTimer::wxListCtrlRenameTimer( wxListCtrl *owner )
+{
+ m_owner = owner;
+}
+
+void wxListCtrlRenameTimer::Notify()
+{
+ m_owner->OnRenameTimer();
+}
+
+//-----------------------------------------------------------------------------
+// wxListCtrlTextCtrlWrapper (internal)
+//-----------------------------------------------------------------------------
+
+BEGIN_EVENT_TABLE(wxListCtrlTextCtrlWrapper, wxEvtHandler)
+ EVT_CHAR (wxListCtrlTextCtrlWrapper::OnChar)
+ EVT_KEY_UP (wxListCtrlTextCtrlWrapper::OnKeyUp)
+ EVT_KILL_FOCUS (wxListCtrlTextCtrlWrapper::OnKillFocus)
+END_EVENT_TABLE()
+
+wxListCtrlTextCtrlWrapper::wxListCtrlTextCtrlWrapper(wxListCtrl *owner,
+ wxTextCtrl *text,
+ long itemEdit)
+ : m_startValue(owner->GetItemText(itemEdit)),
+ m_itemEdited(itemEdit)
+{
+ m_owner = owner;
+ m_text = text;
+ m_finished = false;
+ m_aboutToFinish = false;
+
+ wxRect rectLabel;
+ int offset = 8;
+ owner->GetItemRect(itemEdit, rectLabel);
+
+ m_text->Create(owner, wxID_ANY, m_startValue,
+ wxPoint(rectLabel.x+offset,rectLabel.y),
+ wxSize(rectLabel.width-offset,rectLabel.height));
+ m_text->SetFocus();
+
+ m_text->PushEventHandler(this);
+}
+
+void wxListCtrlTextCtrlWrapper::Finish()
+{
+ if ( !m_finished )
+ {
+ m_finished = true;
+
+ m_text->RemoveEventHandler(this);
+ m_owner->FinishEditing(m_text);
+
+ wxPendingDelete.Append( this );
+ }
+}
+
+bool wxListCtrlTextCtrlWrapper::AcceptChanges()
+{
+ const wxString value = m_text->GetValue();
+
+ if ( value == m_startValue )
+ // nothing changed, always accept
+ return true;
+
+ if ( !m_owner->OnRenameAccept(m_itemEdited, value) )
+ // vetoed by the user
+ return false;
+
+ // accepted, do rename the item
+ m_owner->SetItemText(m_itemEdited, value);
+
+ return true;
+}
+
+void wxListCtrlTextCtrlWrapper::AcceptChangesAndFinish()
+{
+ m_aboutToFinish = true;
+
+ // Notify the owner about the changes
+ AcceptChanges();
+
+ // Even if vetoed, close the control (consistent with MSW)
+ Finish();
+}
+
+void wxListCtrlTextCtrlWrapper::OnChar( wxKeyEvent &event )
+{
+ switch ( event.m_keyCode )
+ {
+ case WXK_RETURN:
+ AcceptChangesAndFinish();
+ break;
+
+ case WXK_ESCAPE:
+ m_owner->OnRenameCancelled( m_itemEdited );
+ Finish();
+ break;
+
+ default:
+ event.Skip();
+ }
+}
+
+void wxListCtrlTextCtrlWrapper::OnKeyUp( wxKeyEvent &event )
+{
+ if (m_finished)
+ {
+ event.Skip();
+ return;
+ }
+
+ // auto-grow the textctrl:
+ wxSize parentSize = m_owner->GetSize();
+ wxPoint myPos = m_text->GetPosition();
+ wxSize mySize = m_text->GetSize();
+ int sx, sy;
+ m_text->GetTextExtent(m_text->GetValue() + _T("MM"), &sx, &sy);
+ if (myPos.x + sx > parentSize.x)
+ sx = parentSize.x - myPos.x;
+ if (mySize.x > sx)
+ sx = mySize.x;
+ m_text->SetSize(sx, wxDefaultCoord);
+
+ event.Skip();
+}
+
+void wxListCtrlTextCtrlWrapper::OnKillFocus( wxFocusEvent &event )
+{
+ if ( !m_finished && !m_aboutToFinish )
+ {
+ if ( !AcceptChanges() )
+ m_owner->OnRenameCancelled( m_itemEdited );
+
+ Finish();
+ }
+
+ // We must let the native text control handle focus
+ event.Skip();
+}
+
+BEGIN_EVENT_TABLE(wxListCtrl, wxControl)
+ EVT_LEFT_DOWN(wxListCtrl::OnLeftDown)
+ EVT_LEFT_DCLICK(wxListCtrl::OnDblClick)
+END_EVENT_TABLE()
+