X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/cc7343106df962079f7b8eaaefbc0514428d3f2a..73486557c0f533a7da12aee1311a3898e4a6f266:/src/generic/listctrl.cpp diff --git a/src/generic/listctrl.cpp b/src/generic/listctrl.cpp index a306732993..fa1cc35090 100644 --- a/src/generic/listctrl.cpp +++ b/src/generic/listctrl.cpp @@ -41,6 +41,10 @@ ... we have it ourselves ... else line->GetFoo(); + + => done + + 5. attributes support: we need OnGetItemAttr() as well! */ // ============================================================================ @@ -54,7 +58,7 @@ #ifdef __GNUG__ #pragma implementation "listctrl.h" #pragma implementation "listctrlbase.h" -#endif +#endif // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -96,6 +100,7 @@ DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_CLICK) DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK) DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK) DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_ACTIVATED) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_CACHE_HINT) // ---------------------------------------------------------------------------- // constants @@ -208,7 +213,7 @@ class WXDLLEXPORT wxListItemData { public: wxListItemData(wxListMainWindow *owner); - ~wxListItemData() { delete m_attr; delete m_rect; } + ~wxListItemData(); void SetItem( const wxListItem &info ); void SetImage( int image ) { m_image = image; } @@ -243,7 +248,8 @@ public: void GetItem( wxListItem &info ) const; - wxListItemAttr *GetAttributes() const { return m_attr; } + void SetAttr(wxListItemAttr *attr) { m_attr = attr; } + wxListItemAttr *GetAttr() const { return m_attr; } public: // the item image or -1 @@ -380,6 +386,9 @@ public: wxString GetText(int index) const; void SetText( int index, const wxString s ); + wxListItemAttr *GetAttr() const; + void SetAttr(wxListItemAttr *attr); + // return true if the highlighting really changed bool Highlight( bool on ); @@ -810,6 +819,9 @@ private: // initialize the current item if needed void UpdateCurrent(); + // delete all items but don't refresh: called from dtor + void DoDeleteAllItems(); + // called when an item is [un]focuded, i.e. becomes [not] current // // currently unused @@ -975,6 +987,18 @@ void wxSelectionStore::OnItemDelete(size_t item) // wxListItemData //----------------------------------------------------------------------------- +wxListItemData::~wxListItemData() +{ + // in the virtual list control the attributes are managed by the main + // program, so don't delete them + if ( !m_owner->IsVirtual() ) + { + delete m_attr; + } + + delete m_rect; +} + void wxListItemData::Init() { m_image = -1; @@ -989,7 +1013,7 @@ wxListItemData::wxListItemData(wxListMainWindow *owner) m_owner = owner; - if ( owner->HasFlag(wxLC_REPORT) ) + if ( owner->InReportView() ) { m_rect = NULL; } @@ -1471,6 +1495,24 @@ int wxListLineData::GetImage( int index ) const return item->GetImage(); } +wxListItemAttr *wxListLineData::GetAttr() const +{ + wxListItemDataList::Node *node = m_items.GetFirst(); + wxCHECK_MSG( node, NULL, _T("invalid column index in GetAttr()") ); + + wxListItemData *item = node->GetData(); + return item->GetAttr(); +} + +void wxListLineData::SetAttr(wxListItemAttr *attr) +{ + wxListItemDataList::Node *node = m_items.GetFirst(); + wxCHECK_RET( node, _T("invalid column index in SetAttr()") ); + + wxListItemData *item = node->GetData(); + item->SetAttr(attr); +} + void wxListLineData::SetAttributes(wxDC *dc, const wxListItemAttr *attr, const wxColour& colText, @@ -1543,11 +1585,10 @@ void wxListLineData::DrawInReportMode( wxDC *dc, // default font wxFont font = listctrl->GetFont(); - // VZ: currently we set the colours/fonts only once, but like this (i.e. - // using SetAttributes() inside the loop), it will be trivial to - // customize the subitems (in report mode) too. - wxListItemData *item = m_items.GetFirst()->GetData(); - wxListItemAttr *attr = item->GetAttributes(); + // TODO: later we should support setting different attributes for + // different columns - to do it, just add "col" argument to + // GetAttr() and move this code into the loop below + wxListItemAttr *attr = GetAttr(); SetAttributes(dc, attr, colText, font, highlighted); bool hasBgCol = attr && attr->HasBackgroundColour(); @@ -2121,7 +2162,7 @@ wxListMainWindow::wxListMainWindow( wxWindow *parent, wxListMainWindow::~wxListMainWindow() { - DeleteEverything(); + DoDeleteAllItems(); delete m_highlightBrush; @@ -2141,6 +2182,7 @@ void wxListMainWindow::CacheLineData(size_t line) } ld->SetImage(listctrl->OnGetItemImage(line)); + ld->SetAttr(listctrl->OnGetItemAttr(line)); } wxListLineData *wxListMainWindow::GetDummyLine() const @@ -2397,7 +2439,6 @@ void wxListMainWindow::RefreshAfter( size_t lineFrom ) CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y ); RefreshRect( rect ); - } else // !report { @@ -2418,6 +2459,12 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) return; } + if ( m_dirty ) + { + // delay the repainting until we calculate all the items positions + return; + } + PrepareDC( dc ); int dev_x, dev_y; @@ -2433,10 +2480,31 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) size_t visibleFrom, visibleTo; GetVisibleLinesRange(&visibleFrom, &visibleTo); + + wxRect rectLine; + wxCoord xOrig, yOrig; + CalcUnscrolledPosition(0, 0, &xOrig, &yOrig); + + // tell the caller cache to cache the data + wxListEvent evCache(wxEVT_COMMAND_LIST_CACHE_HINT, GetParent()->GetId()); + evCache.SetEventObject( GetParent() ); + evCache.m_oldItemIndex = visibleFrom; + evCache.m_itemIndex = visibleTo; + GetParent()->GetEventHandler()->ProcessEvent( evCache ); + for ( size_t line = visibleFrom; line <= visibleTo; line++ ) { + rectLine = GetLineRect(line); + + if ( !IsExposed(rectLine.x - xOrig, rectLine.y - yOrig, + rectLine.width, rectLine.height) ) + { + // don't redraw unaffected lines to avoid flicker + continue; + } + GetLine(line)->DrawInReportMode( &dc, - GetLineRect(line), + rectLine, GetLineHighlightRect(line), IsHighlighted(line) ); } @@ -2665,9 +2733,11 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event ) { // TODO: optimize it too! this is less simple than for report view but // enumerating all items is still not a way to do it!! - for ( current = 0; current < count && !hitResult; current++ ) + for ( current = 0; current < count; current++ ) { hitResult = HitTestLine(current, x, y); + if ( hitResult ) + break; } } @@ -3340,19 +3410,21 @@ void wxListMainWindow::SetItem( wxListItem &item ) wxCHECK_RET( id >= 0 && (size_t)id < GetItemCount(), _T("invalid item index in SetItem") ); - if ( IsVirtual() ) + if ( !IsVirtual() ) + { + wxListLineData *line = GetLine((size_t)id); + line->SetItem( item.m_col, item ); + } + + if ( InReportView() ) { // just refresh the line to show the new value of the text/image RefreshLine((size_t)id); } - else // !virtual + else // !report { + // refresh everything (resulting in horrible flicker - FIXME!) m_dirty = TRUE; - - wxListLineData *line = GetLine((size_t)id); - if ( HasFlag(wxLC_REPORT) ) - item.m_width = GetColumnWidth( item.m_col ); - line->SetItem( item.m_col, item ); } } @@ -3478,7 +3550,10 @@ void wxListMainWindow::SetItemCount(long count) m_selStore.SetItemCount(count); m_countVirt = count; - Refresh(); + ResetVisibleLinesRange(); + + // scrollbars must be reset + m_dirty = TRUE; } int wxListMainWindow::GetSelectedItemCount() @@ -3537,9 +3612,6 @@ bool wxListMainWindow::GetItemPosition(long item, wxPoint& pos) void wxListMainWindow::RecalculatePositions() { - if ( IsEmpty() ) - return; - wxClientDC dc( this ); dc.SetFont( GetFont() ); @@ -3754,6 +3826,7 @@ void wxListMainWindow::DeleteItem( long lindex ) m_lines.RemoveAt( index ); } + m_dirty = TRUE; RefreshAfter(index); } @@ -3767,7 +3840,7 @@ void wxListMainWindow::DeleteColumn( int col ) m_columns.DeleteNode( node ); } -void wxListMainWindow::DeleteAllItems() +void wxListMainWindow::DoDeleteAllItems() { if ( IsEmpty() ) { @@ -3775,8 +3848,6 @@ void wxListMainWindow::DeleteAllItems() return; } - m_dirty = TRUE; - ResetCurrent(); // to make the deletion of all items faster, we don't send the @@ -3792,7 +3863,7 @@ void wxListMainWindow::DeleteAllItems() { m_countVirt = 0; - ResetVisibleLinesRange(); + m_selStore.Clear(); } if ( InReportView() ) @@ -3801,8 +3872,13 @@ void wxListMainWindow::DeleteAllItems() } m_lines.Clear(); +} - m_selStore.Clear(); +void wxListMainWindow::DeleteAllItems() +{ + DoDeleteAllItems(); + + RecalculatePositions(); } void wxListMainWindow::DeleteEverything() @@ -3932,6 +4008,7 @@ void wxListMainWindow::InsertItem( wxListItem &item ) m_lines.Insert( line, id ); + m_dirty = TRUE; RefreshLines(id, GetItemCount() - 1); } @@ -4853,6 +4930,15 @@ int wxListCtrl::OnGetItemImage(long item) const return -1; } +wxListItemAttr *wxListCtrl::OnGetItemAttr(long item) const +{ + wxASSERT_MSG( item >= 0 && item < GetItemCount(), + _T("invalid item index in OnGetItemAttr()") ); + + // no attributes by default + return NULL; +} + void wxListCtrl::SetItemCount(long count) { wxASSERT_MSG( IsVirtual(), _T("this is for virtual controls only") ); @@ -4860,4 +4946,14 @@ void wxListCtrl::SetItemCount(long count) m_mainWin->SetItemCount(count); } +void wxListCtrl::RefreshItem(long item) +{ + m_mainWin->RefreshLine(item); +} + +void wxListCtrl::RefreshItems(long itemFrom, long itemTo) +{ + m_mainWin->RefreshLines(itemFrom, itemTo); +} + #endif // wxUSE_LISTCTRL