X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/8d7eaf91403705cdd94acaae0d7413e711cce3dc..5429cf245532d124c1309ea956a2845eed195485:/src/generic/listctrl.cpp diff --git a/src/generic/listctrl.cpp b/src/generic/listctrl.cpp index c7821beb30..5a55c70613 100644 --- a/src/generic/listctrl.cpp +++ b/src/generic/listctrl.cpp @@ -268,7 +268,7 @@ private: // wxListLineData (internal) //----------------------------------------------------------------------------- -WX_DECLARE_LIST(wxListItemData, wxListItemDataList); +WX_DECLARE_EXPORTED_LIST(wxListItemData, wxListItemDataList); #include "wx/listimpl.cpp" WX_DEFINE_LIST(wxListItemDataList) @@ -392,7 +392,12 @@ private: // draw the text on the DC with the correct justification; also add an // ellipsis if the text is too large to fit in the current width - void DrawTextFormatted(wxDC *dc, const wxString &text, int col, int x, int y, int width); + void DrawTextFormatted(wxDC *dc, + const wxString &text, + int col, + int x, + int yMid, // this is middle, not top, of the text + int width); }; WX_DECLARE_EXPORTED_OBJARRAY(wxListLineData, wxListLineDataArray); @@ -471,13 +476,18 @@ public: }; //----------------------------------------------------------------------------- -// wxListTextCtrl (internal) +// wxListTextCtrlWrapper: wraps a wxTextCtrl to make it work for inline editing //----------------------------------------------------------------------------- -class WXDLLEXPORT wxListTextCtrl: public wxTextCtrl +class WXDLLEXPORT wxListTextCtrlWrapper : public wxEvtHandler { public: - wxListTextCtrl(wxListMainWindow *owner, size_t itemEdit); + // NB: text must be a valid object but not Create()d yet + wxListTextCtrlWrapper(wxListMainWindow *owner, + wxTextCtrl *text, + size_t itemEdit); + + wxTextCtrl *GetText() const { return m_text; } void AcceptChangesAndFinish(); @@ -491,6 +501,7 @@ protected: private: wxListMainWindow *m_owner; + wxTextCtrl *m_text; wxString m_startValue; size_t m_itemEdited; bool m_finished; @@ -503,7 +514,7 @@ private: // wxListMainWindow (internal) //----------------------------------------------------------------------------- -WX_DECLARE_LIST(wxListHeaderData, wxListHeaderDataList); +WX_DECLARE_EXPORTED_LIST(wxListHeaderData, wxListHeaderDataList); #include "wx/listimpl.cpp" WX_DEFINE_LIST(wxListHeaderDataList) @@ -598,7 +609,19 @@ public: void MoveToFocus() { MoveToItem(m_current); } // start editing the label of the given item - void EditLabel( long item ); + wxTextCtrl *EditLabel(long item, + wxClassInfo* textControlClass = CLASSINFO(wxTextCtrl)); + wxTextCtrl *GetEditControl() const + { + return m_textctrlWrapper ? m_textctrlWrapper->GetText() : NULL; + } + + void FinishEditing(wxTextCtrl *text) + { + delete text; + m_textctrlWrapper = NULL; + SetFocusIgnoringChildren(); + } // suspend/resume redrawing the control void Freeze(); @@ -775,8 +798,6 @@ public: m_lineBeforeLastClicked, m_lineSelectSingleOnUp; - wxListTextCtrl* m_textctrl; - protected: wxWindow *GetMainWindowOfCompositeControl() { return GetParent(); } @@ -849,6 +870,11 @@ private: // if this is > 0, the control is frozen and doesn't redraw itself size_t m_freezeCount; + // wrapper around the text control currently used for in place editing or + // NULL if no item is being edited + wxListTextCtrlWrapper *m_textctrlWrapper; + + DECLARE_DYNAMIC_CLASS(wxListMainWindow) DECLARE_EVENT_TABLE() @@ -1477,7 +1503,7 @@ void wxListLineData::DrawInReportMode( wxDC *dc, dc->DrawRectangle( rectHL ); wxCoord x = rect.x + HEADER_OFFSET_X, - y = rect.y + (LINE_SPACING + EXTRA_HEIGHT) / 2; + yMid = rect.y + rect.height/2; size_t col = 0; for ( wxListItemDataList::compatibility_iterator node = m_items.GetFirst(); @@ -1493,8 +1519,8 @@ void wxListLineData::DrawInReportMode( wxDC *dc, if ( item->HasImage() ) { int ix, iy; - m_owner->DrawImage( item->GetImage(), dc, xOld, y ); m_owner->GetImageSize( item->GetImage(), ix, iy ); + m_owner->DrawImage( item->GetImage(), dc, xOld, yMid - iy/2 ); ix += IMAGE_MARGIN_IN_REPORT_MODE; @@ -1502,10 +1528,8 @@ void wxListLineData::DrawInReportMode( wxDC *dc, width -= ix; } - wxDCClipper clipper(*dc, xOld, y, width - 8, rect.height); - if ( item->HasText() ) - DrawTextFormatted(dc, item->GetText(), col, xOld, y, width - 8); + DrawTextFormatted(dc, item->GetText(), col, xOld, yMid, width - 8); } } @@ -1513,18 +1537,21 @@ void wxListLineData::DrawTextFormatted(wxDC *dc, const wxString &text, int col, int x, - int y, + int yMid, int width) { - wxString drawntext, ellipsis; - wxCoord w, h, base_w; - wxListItem item; + wxCoord w, h; + dc->GetTextExtent(text, &w, &h); + + const wxCoord y = yMid - (h + 1)/2; + + wxDCClipper clipper(*dc, x, y, width, h); // determine if the string can fit inside the current width - dc->GetTextExtent(text, &w, &h); if (w <= width) { // it can, draw it using the items alignment + wxListItem item; m_owner->GetColumn(col, item); switch ( item.GetAlign() ) { @@ -1550,13 +1577,14 @@ void wxListLineData::DrawTextFormatted(wxDC *dc, else // otherwise, truncate and add an ellipsis if possible { // determine the base width - ellipsis = wxString(wxT("...")); + wxString ellipsis(wxT("...")); + wxCoord base_w; dc->GetTextExtent(ellipsis, &base_w, &h); // continue until we have enough space or only one character left wxCoord w_c, h_c; size_t len = text.Length(); - drawntext = text.Left(len); + wxString drawntext = text.Left(len); while (len > 1) { dc->GetTextExtent(drawntext.Last(), &w_c, &h_c); @@ -1977,20 +2005,23 @@ void wxListRenameTimer::Notify() } //----------------------------------------------------------------------------- -// wxListTextCtrl (internal) +// wxListTextCtrlWrapper (internal) //----------------------------------------------------------------------------- -BEGIN_EVENT_TABLE(wxListTextCtrl,wxTextCtrl) - EVT_CHAR (wxListTextCtrl::OnChar) - EVT_KEY_UP (wxListTextCtrl::OnKeyUp) - EVT_KILL_FOCUS (wxListTextCtrl::OnKillFocus) +BEGIN_EVENT_TABLE(wxListTextCtrlWrapper, wxEvtHandler) + EVT_CHAR (wxListTextCtrlWrapper::OnChar) + EVT_KEY_UP (wxListTextCtrlWrapper::OnKeyUp) + EVT_KILL_FOCUS (wxListTextCtrlWrapper::OnKillFocus) END_EVENT_TABLE() -wxListTextCtrl::wxListTextCtrl(wxListMainWindow *owner, size_t itemEdit) +wxListTextCtrlWrapper::wxListTextCtrlWrapper(wxListMainWindow *owner, + wxTextCtrl *text, + size_t itemEdit) : m_startValue(owner->GetItemText(itemEdit)), m_itemEdited(itemEdit) { m_owner = owner; + m_text = text; m_finished = false; m_aboutToFinish = false; @@ -1999,27 +2030,28 @@ wxListTextCtrl::wxListTextCtrl(wxListMainWindow *owner, size_t itemEdit) m_owner->CalcScrolledPosition(rectLabel.x, rectLabel.y, &rectLabel.x, &rectLabel.y); - (void)Create(owner, wxID_ANY, m_startValue, - wxPoint(rectLabel.x-4,rectLabel.y-4), - wxSize(rectLabel.width+11,rectLabel.height+8)); + m_text->Create(owner, wxID_ANY, m_startValue, + wxPoint(rectLabel.x-4,rectLabel.y-4), + wxSize(rectLabel.width+11,rectLabel.height+8)); + m_text->PushEventHandler(this); } -void wxListTextCtrl::Finish() +void wxListTextCtrlWrapper::Finish() { if ( !m_finished ) { - wxPendingDelete.Append(this); - m_owner->m_textctrl = NULL; - m_finished = true; - m_owner->SetFocusIgnoringChildren(); + m_text->RemoveEventHandler(this); + m_owner->FinishEditing(m_text); + + delete this; } } -bool wxListTextCtrl::AcceptChanges() +bool wxListTextCtrlWrapper::AcceptChanges() { - const wxString value = GetValue(); + const wxString value = m_text->GetValue(); if ( value == m_startValue ) // nothing changed, always accept @@ -2035,7 +2067,7 @@ bool wxListTextCtrl::AcceptChanges() return true; } -void wxListTextCtrl::AcceptChangesAndFinish() +void wxListTextCtrlWrapper::AcceptChangesAndFinish() { m_aboutToFinish = true; @@ -2046,7 +2078,7 @@ void wxListTextCtrl::AcceptChangesAndFinish() Finish(); } -void wxListTextCtrl::OnChar( wxKeyEvent &event ) +void wxListTextCtrlWrapper::OnChar( wxKeyEvent &event ) { switch ( event.m_keyCode ) { @@ -2064,7 +2096,7 @@ void wxListTextCtrl::OnChar( wxKeyEvent &event ) } } -void wxListTextCtrl::OnKeyUp( wxKeyEvent &event ) +void wxListTextCtrlWrapper::OnKeyUp( wxKeyEvent &event ) { if (m_finished) { @@ -2074,20 +2106,20 @@ void wxListTextCtrl::OnKeyUp( wxKeyEvent &event ) // auto-grow the textctrl: wxSize parentSize = m_owner->GetSize(); - wxPoint myPos = GetPosition(); - wxSize mySize = GetSize(); + wxPoint myPos = m_text->GetPosition(); + wxSize mySize = m_text->GetSize(); int sx, sy; - GetTextExtent(GetValue() + _T("MM"), &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; - SetSize(sx, wxDefaultCoord); + m_text->SetSize(sx, wxDefaultCoord); event.Skip(); } -void wxListTextCtrl::OnKillFocus( wxFocusEvent &event ) +void wxListTextCtrlWrapper::OnKillFocus( wxFocusEvent &event ) { if ( !m_finished && !m_aboutToFinish ) { @@ -2143,7 +2175,7 @@ void wxListMainWindow::Init() m_lastOnSame = false; m_renameTimer = new wxListRenameTimer( this ); - m_textctrl = NULL; + m_textctrlWrapper = NULL; m_current = m_lineLastClicked = @@ -2751,31 +2783,37 @@ void wxListMainWindow::ChangeCurrent(size_t current) SendNotify(current, wxEVT_COMMAND_LIST_ITEM_FOCUSED); } -void wxListMainWindow::EditLabel( long item ) +wxTextCtrl *wxListMainWindow::EditLabel(long item, wxClassInfo* textControlClass) { - wxCHECK_RET( (item >= 0) && ((size_t)item < GetItemCount()), + wxCHECK_MSG( (item >= 0) && ((size_t)item < GetItemCount()), NULL, wxT("wrong index in wxGenericListCtrl::EditLabel()") ); + wxASSERT_MSG( textControlClass->IsKindOf(CLASSINFO(wxTextCtrl)), + wxT("EditLabel() needs a text control") ); + size_t itemEdit = (size_t)item; wxListEvent le( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT, GetParent()->GetId() ); le.SetEventObject( GetParent() ); le.m_itemIndex = item; wxListLineData *data = GetLine(itemEdit); - wxCHECK_RET( data, _T("invalid index in EditLabel()") ); + wxCHECK_MSG( data, NULL, _T("invalid index in EditLabel()") ); data->GetItem( 0, le.m_item ); if ( GetParent()->GetEventHandler()->ProcessEvent( le ) && !le.IsAllowed() ) + { // vetoed by user code - return; + return NULL; + } // We have to call this here because the label in question might just have // been added and no screen update taken place. if ( m_dirty ) wxSafeYield(); - m_textctrl = new wxListTextCtrl(this, itemEdit); - m_textctrl->SetFocus(); + wxTextCtrl * const text = (wxTextCtrl *)textControlClass->CreateObject(); + m_textctrlWrapper = new wxListTextCtrlWrapper(this, text, item); + return m_textctrlWrapper->GetText(); } void wxListMainWindow::OnRenameTimer() @@ -2825,9 +2863,9 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event ) // shutdown the edit control when the mouse is clicked elsewhere on the // listctrl because the order of events is different (or something like // that), so explicitly end the edit if it is active. - if ( event.LeftDown() && m_textctrl) - m_textctrl->AcceptChangesAndFinish(); -#endif + if ( event.LeftDown() && m_textctrlWrapper ) + m_textctrlWrapper->AcceptChangesAndFinish(); +#endif // __WXMAC__ event.SetEventObject( GetParent() ); if ( GetParent()->GetEventHandler()->ProcessEvent( event) ) @@ -2911,7 +2949,8 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event ) if ( !hitResult ) { - // outside of any item + // outside of any item, reset the selection and bail out + HighlightAll(false); return; } @@ -4896,11 +4935,18 @@ bool wxGenericListCtrl::SetItemState( long item, long state, long stateMask ) bool wxGenericListCtrl::SetItemImage( long item, int image, int WXUNUSED(selImage) ) +{ + return SetItemColumnImage(item, 0, image); +} + +bool +wxGenericListCtrl::SetItemColumnImage( long item, long column, int image ) { wxListItem info; info.m_image = image; info.m_mask = wxLIST_MASK_IMAGE; info.m_itemId = item; + info.m_col = column; m_mainWin->SetItem( info ); return true; } @@ -5150,9 +5196,15 @@ bool wxGenericListCtrl::DeleteColumn( int col ) return true; } -void wxGenericListCtrl::Edit( long item ) +wxTextCtrl *wxGenericListCtrl::EditLabel(long item, + wxClassInfo* textControlClass) { - m_mainWin->EditLabel( item ); + return m_mainWin->EditLabel( item, textControlClass ); +} + +wxTextCtrl *wxGenericListCtrl::GetEditControl() const +{ + return m_mainWin->GetEditControl(); } bool wxGenericListCtrl::EnsureVisible( long item ) @@ -5432,6 +5484,16 @@ bool wxGenericListCtrl::DoPopupMenu( wxMenu *menu, int x, int y ) #endif } +void wxGenericListCtrl::DoClientToScreen( int *x, int *y ) const +{ + return m_mainWin->DoClientToScreen(x, y); +} + +void wxGenericListCtrl::DoScreenToClient( int *x, int *y ) const +{ + return m_mainWin->DoScreenToClient(x, y); +} + void wxGenericListCtrl::SetFocus() { // The test in window.cpp fails as we are a composite