X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ac53090cb7f990f58bbe54903fd2a6f206fd4a53..83e96c90f82279b6404cff14ebab4b0aa4f32480:/src/generic/listctrl.cpp?ds=sidebyside diff --git a/src/generic/listctrl.cpp b/src/generic/listctrl.cpp index 0a9299f9df..33b696bd23 100644 --- a/src/generic/listctrl.cpp +++ b/src/generic/listctrl.cpp @@ -23,7 +23,7 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "listctrl.h" #pragma implementation "listctrlbase.h" #endif @@ -68,13 +68,10 @@ IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxGenericListCtrl) #endif // HAVE_NATIVE_LISTCTRL/!HAVE_NATIVE_LISTCTRL -#if defined(__WXGTK__) - #include - #include "wx/gtk/win_gtk.h" -#endif - #include "wx/selstore.h" +#include "wx/renderer.h" + // ---------------------------------------------------------------------------- // events // ---------------------------------------------------------------------------- @@ -106,12 +103,10 @@ DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_CACHE_HINT) // constants // ---------------------------------------------------------------------------- -// the height of the header window (FIXME: should depend on its font!) -static const int HEADER_HEIGHT = 23; +// // the height of the header window (FIXME: should depend on its font!) +// static const int HEADER_HEIGHT = 23; -// the scrollbar units static const int SCROLL_UNIT_X = 15; -static const int SCROLL_UNIT_Y = 15; // the spacing between the lines (in report mode) static const int LINE_SPACING = 0; @@ -120,10 +115,17 @@ static const int LINE_SPACING = 0; static const int EXTRA_WIDTH = 3; static const int EXTRA_HEIGHT = 4; +// margin between the window and the items +static const int EXTRA_BORDER_X = 2; +static const int EXTRA_BORDER_Y = 2; + // offset for the header window static const int HEADER_OFFSET_X = 1; static const int HEADER_OFFSET_Y = 1; +// margin between rows of icons in [small] icon view +static const int MARGIN_BETWEEN_ROWS = 6; + // when autosizing the columns, add some slack static const int AUTOSIZE_COL_MARGIN = 10; @@ -258,7 +260,7 @@ WX_DECLARE_LIST(wxListItemData, wxListItemDataList); #include "wx/listimpl.cpp" WX_DEFINE_LIST(wxListItemDataList); -class WXDLLEXPORT wxListLineData +class wxListLineData { public: // the list of subitems: only may have more than one item in report mode @@ -278,6 +280,18 @@ public: // the part to be highlighted wxRect m_rectHighlight; + + // extend all our rects to be centered inside theo ne of given width + void ExtendWidth(wxCoord w) + { + wxASSERT_MSG( m_rectAll.width <= w, + _T("width can only be increased") ); + + m_rectAll.width = w; + m_rectLabel.x = m_rectAll.x + (w - m_rectLabel.width)/2; + m_rectIcon.x = m_rectAll.x + (w - m_rectIcon.width)/2; + m_rectHighlight.x = m_rectAll.x + (w - m_rectHighlight.width)/2; + } } *m_gi; // is this item selected? [NB: not used in virtual mode] @@ -289,7 +303,11 @@ public: public: wxListLineData(wxListMainWindow *owner); - ~wxListLineData() { delete m_gi; } + ~wxListLineData() + { + WX_CLEAR_LIST(wxListItemDataList, m_items); + delete m_gi; + } // are we in report mode? inline bool InReportView() const; @@ -304,7 +322,7 @@ public: void CalculateSize( wxDC *dc, int spacing ); // remember the position this line appears at - void SetPosition( int x, int y, int window_width, int spacing ); + void SetPosition( int x, int y, int spacing ); // wxListCtrl API @@ -405,7 +423,6 @@ public: virtual ~wxListHeaderWindow(); - void DoDrawRect( wxDC *dc, int x, int y, int w, int h ); void DrawCurrent(); void AdjustDC(wxDC& dc); @@ -476,7 +493,7 @@ WX_DECLARE_LIST(wxListHeaderData, wxListHeaderDataList); #include "wx/listimpl.cpp" WX_DEFINE_LIST(wxListHeaderDataList); -class WXDLLEXPORT wxListMainWindow : public wxScrolledWindow +class wxListMainWindow : public wxScrolledWindow { public: wxListMainWindow(); @@ -577,6 +594,7 @@ public: void OnRenameTimer(); bool OnRenameAccept(size_t itemEdit, const wxString& value); + void OnRenameCancelled(size_t itemEdit); void OnMouse( wxMouseEvent &event ); @@ -615,6 +633,7 @@ public: void SetItemState( long item, long state, long stateMask ); int GetItemState( long item, long stateMask ) const; void GetItemRect( long index, wxRect &rect ) const; + wxRect GetViewRect() const; bool GetItemPosition( long item, wxPoint& pos ) const; int GetSelectedItemCount() const; @@ -722,8 +741,6 @@ public: bool m_dirty; wxColour *m_highlightColour; - int m_xScroll, - m_yScroll; wxImageListType *m_small_image_list; wxImageListType *m_normal_image_list; int m_small_spacing; @@ -751,9 +768,6 @@ protected: // common part of all ctors void Init(); - // intiialize m_[xy]Scroll - void InitScrolling(); - // get the line data for the given index wxListLineData *GetLine(size_t n) const { @@ -1089,7 +1103,6 @@ inline bool wxListLineData::IsVirtual() const wxListLineData::wxListLineData( wxListMainWindow *owner ) { m_owner = owner; - m_items.DeleteContents( TRUE ); if ( InReportView() ) { @@ -1107,101 +1120,94 @@ wxListLineData::wxListLineData( wxListMainWindow *owner ) void wxListLineData::CalculateSize( wxDC *dc, int spacing ) { - wxListItemDataList::Node *node = m_items.GetFirst(); + wxListItemDataList::compatibility_iterator node = m_items.GetFirst(); wxCHECK_RET( node, _T("no subitems at all??") ); wxListItemData *item = node->GetData(); + wxString s; + wxCoord lw, lh; + switch ( GetMode() ) { case wxLC_ICON: case wxLC_SMALL_ICON: - { - m_gi->m_rectAll.width = spacing; + m_gi->m_rectAll.width = spacing; - wxString s = item->GetText(); + s = item->GetText(); - wxCoord lw, lh; - if ( s.empty() ) - { - lh = - m_gi->m_rectLabel.width = - m_gi->m_rectLabel.height = 0; - } - else // has label - { - dc->GetTextExtent( s, &lw, &lh ); - if (lh < SCROLL_UNIT_Y) - lh = SCROLL_UNIT_Y; - lw += EXTRA_WIDTH; - lh += EXTRA_HEIGHT; - - m_gi->m_rectAll.height = spacing + lh; - if (lw > spacing) - m_gi->m_rectAll.width = lw; - - m_gi->m_rectLabel.width = lw; - m_gi->m_rectLabel.height = lh; - } - - if (item->HasImage()) - { - int w, h; - m_owner->GetImageSize( item->GetImage(), w, h ); - m_gi->m_rectIcon.width = w + 8; - m_gi->m_rectIcon.height = h + 8; - - if ( m_gi->m_rectIcon.width > m_gi->m_rectAll.width ) - m_gi->m_rectAll.width = m_gi->m_rectIcon.width; - if ( m_gi->m_rectIcon.height + lh > m_gi->m_rectAll.height - 4 ) - m_gi->m_rectAll.height = m_gi->m_rectIcon.height + lh + 4; - } - - if ( item->HasText() ) - { - m_gi->m_rectHighlight.width = m_gi->m_rectLabel.width; - m_gi->m_rectHighlight.height = m_gi->m_rectLabel.height; - } - else // no text, highlight the icon - { - m_gi->m_rectHighlight.width = m_gi->m_rectIcon.width; - m_gi->m_rectHighlight.height = m_gi->m_rectIcon.height; - } + if ( s.empty() ) + { + lh = + m_gi->m_rectLabel.width = + m_gi->m_rectLabel.height = 0; } - break; - - case wxLC_LIST: + else // has label { - wxString s = item->GetTextForMeasuring(); - - wxCoord lw,lh; dc->GetTextExtent( s, &lw, &lh ); - if (lh < SCROLL_UNIT_Y) - lh = SCROLL_UNIT_Y; lw += EXTRA_WIDTH; lh += EXTRA_HEIGHT; + m_gi->m_rectAll.height = spacing + lh; + if (lw > spacing) + m_gi->m_rectAll.width = lw; + m_gi->m_rectLabel.width = lw; m_gi->m_rectLabel.height = lh; + } - m_gi->m_rectAll.width = lw; - m_gi->m_rectAll.height = lh; + if (item->HasImage()) + { + int w, h; + m_owner->GetImageSize( item->GetImage(), w, h ); + m_gi->m_rectIcon.width = w + 8; + m_gi->m_rectIcon.height = h + 8; + + if ( m_gi->m_rectIcon.width > m_gi->m_rectAll.width ) + m_gi->m_rectAll.width = m_gi->m_rectIcon.width; + if ( m_gi->m_rectIcon.height + lh > m_gi->m_rectAll.height - 4 ) + m_gi->m_rectAll.height = m_gi->m_rectIcon.height + lh + 4; + } - if (item->HasImage()) - { - int w, h; - m_owner->GetImageSize( item->GetImage(), w, h ); - m_gi->m_rectIcon.width = w; - m_gi->m_rectIcon.height = h; - - m_gi->m_rectAll.width += 4 + w; - if (h > m_gi->m_rectAll.height) - m_gi->m_rectAll.height = h; - } + if ( item->HasText() ) + { + m_gi->m_rectHighlight.width = m_gi->m_rectLabel.width; + m_gi->m_rectHighlight.height = m_gi->m_rectLabel.height; + } + else // no text, highlight the icon + { + m_gi->m_rectHighlight.width = m_gi->m_rectIcon.width; + m_gi->m_rectHighlight.height = m_gi->m_rectIcon.height; + } + break; + + case wxLC_LIST: + s = item->GetTextForMeasuring(); + + dc->GetTextExtent( s, &lw, &lh ); + lw += EXTRA_WIDTH; + lh += EXTRA_HEIGHT; + + m_gi->m_rectLabel.width = lw; + m_gi->m_rectLabel.height = lh; - m_gi->m_rectHighlight.width = m_gi->m_rectAll.width; - m_gi->m_rectHighlight.height = m_gi->m_rectAll.height; + m_gi->m_rectAll.width = lw; + m_gi->m_rectAll.height = lh; + + if (item->HasImage()) + { + int w, h; + m_owner->GetImageSize( item->GetImage(), w, h ); + m_gi->m_rectIcon.width = w; + m_gi->m_rectIcon.height = h; + + m_gi->m_rectAll.width += 4 + w; + if (h > m_gi->m_rectAll.height) + m_gi->m_rectAll.height = h; } + + m_gi->m_rectHighlight.width = m_gi->m_rectAll.width; + m_gi->m_rectHighlight.height = m_gi->m_rectAll.height; break; case wxLC_REPORT: @@ -1213,11 +1219,9 @@ void wxListLineData::CalculateSize( wxDC *dc, int spacing ) } } -void wxListLineData::SetPosition( int x, int y, - int window_width, - int spacing ) +void wxListLineData::SetPosition( int x, int y, int spacing ) { - wxListItemDataList::Node *node = m_items.GetFirst(); + wxListItemDataList::compatibility_iterator node = m_items.GetFirst(); wxCHECK_RET( node, _T("no subitems at all??") ); wxListItemData *item = node->GetData(); @@ -1290,7 +1294,7 @@ void wxListLineData::InitItems( int num ) void wxListLineData::SetItem( int index, const wxListItem &info ) { - wxListItemDataList::Node *node = m_items.Item( index ); + wxListItemDataList::compatibility_iterator node = m_items.Item( index ); wxCHECK_RET( node, _T("invalid column index in SetItem") ); wxListItemData *item = node->GetData(); @@ -1299,7 +1303,7 @@ void wxListLineData::SetItem( int index, const wxListItem &info ) void wxListLineData::GetItem( int index, wxListItem &info ) { - wxListItemDataList::Node *node = m_items.Item( index ); + wxListItemDataList::compatibility_iterator node = m_items.Item( index ); if (node) { wxListItemData *item = node->GetData(); @@ -1311,7 +1315,7 @@ wxString wxListLineData::GetText(int index) const { wxString s; - wxListItemDataList::Node *node = m_items.Item( index ); + wxListItemDataList::compatibility_iterator node = m_items.Item( index ); if (node) { wxListItemData *item = node->GetData(); @@ -1323,7 +1327,7 @@ wxString wxListLineData::GetText(int index) const void wxListLineData::SetText( int index, const wxString s ) { - wxListItemDataList::Node *node = m_items.Item( index ); + wxListItemDataList::compatibility_iterator node = m_items.Item( index ); if (node) { wxListItemData *item = node->GetData(); @@ -1333,7 +1337,7 @@ void wxListLineData::SetText( int index, const wxString s ) void wxListLineData::SetImage( int index, int image ) { - wxListItemDataList::Node *node = m_items.Item( index ); + wxListItemDataList::compatibility_iterator node = m_items.Item( index ); wxCHECK_RET( node, _T("invalid column index in SetImage()") ); wxListItemData *item = node->GetData(); @@ -1342,7 +1346,7 @@ void wxListLineData::SetImage( int index, int image ) int wxListLineData::GetImage( int index ) const { - wxListItemDataList::Node *node = m_items.Item( index ); + wxListItemDataList::compatibility_iterator node = m_items.Item( index ); wxCHECK_MSG( node, -1, _T("invalid column index in GetImage()") ); wxListItemData *item = node->GetData(); @@ -1351,7 +1355,7 @@ int wxListLineData::GetImage( int index ) const wxListItemAttr *wxListLineData::GetAttr() const { - wxListItemDataList::Node *node = m_items.GetFirst(); + wxListItemDataList::compatibility_iterator node = m_items.GetFirst(); wxCHECK_MSG( node, NULL, _T("invalid column index in GetAttr()") ); wxListItemData *item = node->GetData(); @@ -1360,7 +1364,7 @@ wxListItemAttr *wxListLineData::GetAttr() const void wxListLineData::SetAttr(wxListItemAttr *attr) { - wxListItemDataList::Node *node = m_items.GetFirst(); + wxListItemDataList::compatibility_iterator node = m_items.GetFirst(); wxCHECK_RET( node, _T("invalid column index in SetAttr()") ); wxListItemData *item = node->GetData(); @@ -1433,7 +1437,7 @@ bool wxListLineData::SetAttributes(wxDC *dc, void wxListLineData::Draw( wxDC *dc ) { - wxListItemDataList::Node *node = m_items.GetFirst(); + wxListItemDataList::compatibility_iterator node = m_items.GetFirst(); wxCHECK_RET( node, _T("no subitems at all??") ); bool highlighted = IsHighlighted(); @@ -1445,20 +1449,31 @@ void wxListLineData::Draw( wxDC *dc ) dc->DrawRectangle( m_gi->m_rectHighlight ); } + // just for debugging to better see where the items are +#if 0 + dc->SetPen(*wxRED_PEN); + dc->SetBrush(*wxTRANSPARENT_BRUSH); + dc->DrawRectangle( m_gi->m_rectAll ); + dc->SetPen(*wxGREEN_PEN); + dc->DrawRectangle( m_gi->m_rectIcon ); +#endif // 0 + wxListItemData *item = node->GetData(); if (item->HasImage()) { - wxRect rectIcon = m_gi->m_rectIcon; - m_owner->DrawImage( item->GetImage(), dc, - rectIcon.x, rectIcon.y ); + // centre the image inside our rectangle, this looks nicer when items + // ae aligned in a row + const wxRect& rectIcon = m_gi->m_rectIcon; + + m_owner->DrawImage(item->GetImage(), dc, rectIcon.x, rectIcon.y); } if (item->HasText()) { - wxRect rectLabel = m_gi->m_rectLabel; + const wxRect& rectLabel = m_gi->m_rectLabel; wxDCClipper clipper(*dc, rectLabel); - dc->DrawText( item->GetText(), rectLabel.x, rectLabel.y ); + dc->DrawText(item->GetText(), rectLabel.x, rectLabel.y); } } @@ -1480,7 +1495,7 @@ void wxListLineData::DrawInReportMode( wxDC *dc, y = rect.y + (LINE_SPACING + EXTRA_HEIGHT) / 2; size_t col = 0; - for ( wxListItemDataList::Node *node = m_items.GetFirst(); + for ( wxListItemDataList::compatibility_iterator node = m_items.GetFirst(); node; node = node->GetNext(), col++ ) { @@ -1653,66 +1668,6 @@ wxListHeaderWindow::~wxListHeaderWindow() #include "wx/univ/theme.h" #endif -void wxListHeaderWindow::DoDrawRect( wxDC *dc, int x, int y, int w, int h ) -{ -#if defined(__WXGTK__) && !defined(__WXUNIVERSAL__) - GtkStateType state = m_parent->IsEnabled() ? GTK_STATE_NORMAL - : GTK_STATE_INSENSITIVE; - - x = dc->XLOG2DEV( x ); - - gtk_paint_box (m_wxwindow->style, GTK_PIZZA(m_wxwindow)->bin_window, - state, GTK_SHADOW_OUT, - (GdkRectangle*) NULL, m_wxwindow, - (char *)"button", // const_cast - x-1, y-1, w+2, h+2); -#elif defined(__WXUNIVERSAL__) - wxTheme *theme = wxTheme::Get(); - wxRenderer *renderer = theme->GetRenderer(); - renderer->DrawBorder( *dc, wxBORDER_RAISED, wxRect(x,y,w,h), 0 ); -#elif defined(__WXMAC__) - const int m_corner = 1; - - dc->SetBrush( *wxTRANSPARENT_BRUSH ); - - dc->SetPen( wxPen( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNSHADOW ) , 1 , wxSOLID ) ); - dc->DrawLine( x+w-m_corner+1, y, x+w, y+h ); // right (outer) - dc->DrawRectangle( x, y+h, w+1, 1 ); // bottom (outer) - - wxPen pen( wxColour( 0x88 , 0x88 , 0x88 ), 1, wxSOLID ); - - dc->SetPen( pen ); - dc->DrawLine( x+w-m_corner, y, x+w-1, y+h ); // right (inner) - dc->DrawRectangle( x+1, y+h-1, w-2, 1 ); // bottom (inner) - - dc->SetPen( *wxWHITE_PEN ); - dc->DrawRectangle( x, y, w-m_corner+1, 1 ); // top (outer) - dc->DrawRectangle( x, y, 1, h ); // left (outer) - dc->DrawLine( x, y+h-1, x+1, y+h-1 ); - dc->DrawLine( x+w-1, y, x+w-1, y+1 ); -#else // !GTK, !Mac - const int m_corner = 1; - - dc->SetBrush( *wxTRANSPARENT_BRUSH ); - - dc->SetPen( *wxBLACK_PEN ); - dc->DrawLine( x+w-m_corner+1, y, x+w, y+h ); // right (outer) - dc->DrawRectangle( x, y+h, w+1, 1 ); // bottom (outer) - - wxPen pen( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNSHADOW ), 1, wxSOLID ); - - dc->SetPen( pen ); - dc->DrawLine( x+w-m_corner, y, x+w-1, y+h ); // right (inner) - dc->DrawRectangle( x+1, y+h-1, w-2, 1 ); // bottom (inner) - - dc->SetPen( *wxWHITE_PEN ); - dc->DrawRectangle( x, y, w-m_corner+1, 1 ); // top (outer) - dc->DrawRectangle( x, y, 1, h ); // left (outer) - dc->DrawLine( x, y+h-1, x+1, y+h-1 ); - dc->DrawLine( x+w-1, y, x+w-1, y+1 ); -#endif -} - // shift the DC origin to match the position of the main window horz // scrollbar: this allows us to always use logical coords void wxListHeaderWindow::AdjustDC(wxDC& dc) @@ -1729,11 +1684,7 @@ void wxListHeaderWindow::AdjustDC(wxDC& dc) void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) { -#if defined(__WXGTK__) - wxClientDC dc( this ); -#else wxPaintDC dc( this ); -#endif PrepareDC( dc ); AdjustDC( dc ); @@ -1768,9 +1719,14 @@ void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) // inside the column rect int cw = wCol - 2; - dc.SetPen( *wxWHITE_PEN ); - - DoDrawRect( &dc, x, HEADER_OFFSET_Y, cw, h-2 ); + wxRendererNative::Get().DrawHeaderButton + ( + this, + dc, + wxRect(x, HEADER_OFFSET_Y, cw, h - 2), + m_parent->IsEnabled() ? 0 + : wxCONTROL_DISABLED + ); // see if we have enough space for the column label @@ -2105,6 +2061,7 @@ void wxListTextCtrl::OnChar( wxKeyEvent &event ) case WXK_ESCAPE: Finish(); + m_owner->OnRenameCancelled( m_itemEdited ); break; default: @@ -2139,9 +2096,11 @@ void wxListTextCtrl::OnKillFocus( wxFocusEvent &event ) { if ( !m_finished ) { - (void)AcceptChanges(); - + // We must finish regardless of success, otherwise we'll get focus problems Finish(); + + if ( !AcceptChanges() ) + m_owner->OnRenameCancelled( m_itemEdited ); } event.Skip(); @@ -2165,7 +2124,6 @@ END_EVENT_TABLE() void wxListMainWindow::Init() { - m_columns.DeleteContents( TRUE ); m_dirty = TRUE; m_countVirt = 0; m_lineFrom = @@ -2195,29 +2153,12 @@ void wxListMainWindow::Init() m_freezeCount = 0; } -void wxListMainWindow::InitScrolling() -{ - if ( HasFlag(wxLC_REPORT) ) - { - m_xScroll = SCROLL_UNIT_X; - m_yScroll = SCROLL_UNIT_Y; - } - else - { - m_xScroll = SCROLL_UNIT_Y; - m_yScroll = 0; - } -} - wxListMainWindow::wxListMainWindow() { Init(); m_highlightBrush = m_highlightUnfocusedBrush = (wxBrush *) NULL; - - m_xScroll = - m_yScroll = 0; } wxListMainWindow::wxListMainWindow( wxWindow *parent, @@ -2252,8 +2193,7 @@ wxListMainWindow::wxListMainWindow( wxWindow *parent, wxSize sz = size; sz.y = 25; - InitScrolling(); - SetScrollbars( m_xScroll, m_yScroll, 0, 0, 0, 0 ); + SetScrollbars( 0, 0, 0, 0, 0, 0 ); SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOX ) ); } @@ -2261,6 +2201,7 @@ wxListMainWindow::wxListMainWindow( wxWindow *parent, wxListMainWindow::~wxListMainWindow() { DoDeleteAllItems(); + WX_CLEAR_LIST(wxListHeaderDataList, m_columns); delete m_highlightBrush; delete m_highlightUnfocusedBrush; @@ -2320,8 +2261,6 @@ wxListLineData *wxListMainWindow::GetDummyLine() const wxCoord wxListMainWindow::GetLineHeight() const { - wxASSERT_MSG( HasFlag(wxLC_REPORT), _T("only works in report mode") ); - // we cache the line height as calling GetTextExtent() is slow if ( !m_lineHeight ) { @@ -2333,9 +2272,6 @@ wxCoord wxListMainWindow::GetLineHeight() const wxCoord y; dc.GetTextExtent(_T("H"), NULL, &y); - if ( y < SCROLL_UNIT_Y ) - y = SCROLL_UNIT_Y; - if ( m_small_image_list && m_small_image_list->GetImageCount() ) { int iw = 0; @@ -2735,7 +2671,6 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) { wxPen pen(GetRuleColour(), 1, wxSOLID); - int col = 0; wxRect firstItemRect; wxRect lastItemRect; GetItemRect(visibleFrom, firstItemRect); @@ -2743,7 +2678,7 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) int x = firstItemRect.GetX(); dc.SetPen(pen); dc.SetBrush(* wxTRANSPARENT_BRUSH); - for (col = 0; col < GetColumnCount(); col++) + for (int col = 0; col < GetColumnCount(); col++) { int colWidth = GetColumnWidth(col); x += colWidth; @@ -2887,6 +2822,24 @@ bool wxListMainWindow::OnRenameAccept(size_t itemEdit, const wxString& value) le.IsAllowed(); } +void wxListMainWindow::OnRenameCancelled(size_t itemEdit) +{ + // let owner know that the edit was cancelled + wxListEvent le( wxEVT_COMMAND_LIST_END_LABEL_EDIT, GetParent()->GetId() ); + + le.SetEditCanceled(TRUE); + + le.SetEventObject( GetParent() ); + le.m_itemIndex = itemEdit; + + wxListLineData *data = GetLine(itemEdit); + wxCHECK_RET( data, _T("invalid index in OnRenameCancelled()") ); + + data->GetItem( 0, le.m_item ); + + GetEventHandler()->ProcessEvent( le ); +} + void wxListMainWindow::OnMouse( wxMouseEvent &event ) { event.SetEventObject( GetParent() ); @@ -3072,8 +3025,10 @@ void wxListMainWindow::MoveToItem(size_t item) int client_w, client_h; GetClientSize( &client_w, &client_h ); - int view_x = m_xScroll*GetScrollPos( wxHORIZONTAL ); - int view_y = m_yScroll*GetScrollPos( wxVERTICAL ); + const int hLine = GetLineHeight(); + + int view_x = SCROLL_UNIT_X*GetScrollPos( wxHORIZONTAL ); + int view_y = hLine*GetScrollPos( wxVERTICAL ); if ( HasFlag(wxLC_REPORT) ) { @@ -3082,16 +3037,16 @@ void wxListMainWindow::MoveToItem(size_t item) ResetVisibleLinesRange(); if (rect.y < view_y ) - Scroll( -1, rect.y/m_yScroll ); + Scroll( -1, rect.y/hLine ); if (rect.y+rect.height+5 > view_y+client_h) - Scroll( -1, (rect.y+rect.height-client_h+SCROLL_UNIT_Y)/m_yScroll ); + Scroll( -1, (rect.y+rect.height-client_h+hLine)/hLine ); } else // !report { if (rect.x-view_x < 5) - Scroll( (rect.x-5)/m_xScroll, -1 ); + Scroll( (rect.x-5)/SCROLL_UNIT_X, -1 ); if (rect.x+rect.width-5 > view_x+client_w) - Scroll( (rect.x+rect.width-client_w+SCROLL_UNIT_X)/m_xScroll, -1 ); + Scroll( (rect.x+rect.width-client_w+SCROLL_UNIT_X)/SCROLL_UNIT_X, -1 ); } } @@ -3231,15 +3186,7 @@ void wxListMainWindow::OnChar( wxKeyEvent &event ) case WXK_PRIOR: { - int steps = 0; - if ( HasFlag(wxLC_REPORT) ) - { - steps = m_linesPerPage - 1; - } - else - { - steps = m_current % m_linesPerPage; - } + int steps = HasFlag(wxLC_REPORT) ? m_linesPerPage - 1 : m_current % m_linesPerPage; int index = m_current - steps; if (index < 0) @@ -3251,15 +3198,9 @@ void wxListMainWindow::OnChar( wxKeyEvent &event ) case WXK_NEXT: { - int steps = 0; - if ( HasFlag(wxLC_REPORT) ) - { - steps = m_linesPerPage - 1; - } - else - { - steps = m_linesPerPage - (m_current % m_linesPerPage) - 1; - } + int steps = HasFlag(wxLC_REPORT) + ? m_linesPerPage - 1 + : m_linesPerPage - (m_current % m_linesPerPage) - 1; size_t index = m_current + steps; size_t count = GetItemCount(); @@ -3346,6 +3287,14 @@ void wxListMainWindow::SetFocus() void wxListMainWindow::OnSetFocus( wxFocusEvent &WXUNUSED(event) ) { + if ( GetParent() ) + { + wxFocusEvent event( wxEVT_SET_FOCUS, GetParent()->GetId() ); + event.SetEventObject( GetParent() ); + if ( GetParent()->GetEventHandler()->ProcessEvent( event) ) + return; + } + // wxGTK sends us EVT_SET_FOCUS events even if we had never got // EVT_KILL_FOCUS before which means that we finish by redrawing the items // which are already drawn correctly resulting in horrible flicker - avoid @@ -3356,19 +3305,18 @@ void wxListMainWindow::OnSetFocus( wxFocusEvent &WXUNUSED(event) ) RefreshSelected(); } - - if ( !GetParent() ) - return; - - wxFocusEvent event( wxEVT_SET_FOCUS, GetParent()->GetId() ); - event.SetEventObject( GetParent() ); - GetParent()->GetEventHandler()->ProcessEvent( event ); } void wxListMainWindow::OnKillFocus( wxFocusEvent &WXUNUSED(event) ) { + if ( GetParent() ) + { + wxFocusEvent event( wxEVT_KILL_FOCUS, GetParent()->GetId() ); + event.SetEventObject( GetParent() ); + if ( GetParent()->GetEventHandler()->ProcessEvent( event) ) + return; + } m_hasFocus = FALSE; - RefreshSelected(); } @@ -3478,7 +3426,7 @@ int wxListMainWindow::GetItemSpacing( bool isSmall ) void wxListMainWindow::SetColumn( int col, wxListItem &item ) { - wxListHeaderDataList::Node *node = m_columns.Item( col ); + wxListHeaderDataList::compatibility_iterator node = m_columns.Item( col ); wxCHECK_RET( node, _T("invalid column index in SetColumn") ); @@ -3511,7 +3459,7 @@ void wxListMainWindow::SetColumnWidth( int col, int width ) if ( headerWin ) headerWin->m_dirty = TRUE; - wxListHeaderDataList::Node *node = m_columns.Item( col ); + wxListHeaderDataList::compatibility_iterator node = m_columns.Item( col ); wxCHECK_RET( node, _T("no column?") ); wxListHeaderData *column = node->GetData(); @@ -3539,7 +3487,7 @@ void wxListMainWindow::SetColumnWidth( int col, int width ) for ( size_t i = 0; i < count; i++ ) { wxListLineData *line = GetLine(i); - wxListItemDataList::Node *n = line->m_items.Item( col ); + wxListItemDataList::compatibility_iterator n = line->m_items.Item( col ); wxCHECK_RET( n, _T("no subitem?") ); @@ -3592,7 +3540,7 @@ int wxListMainWindow::GetHeaderWidth() const void wxListMainWindow::GetColumn( int col, wxListItem &item ) const { - wxListHeaderDataList::Node *node = m_columns.Item( col ); + wxListHeaderDataList::compatibility_iterator node = m_columns.Item( col ); wxCHECK_RET( node, _T("invalid column index in GetColumn") ); wxListHeaderData *column = node->GetData(); @@ -3601,7 +3549,7 @@ void wxListMainWindow::GetColumn( int col, wxListItem &item ) const int wxListMainWindow::GetColumnWidth( int col ) const { - wxListHeaderDataList::Node *node = m_columns.Item( col ); + wxListHeaderDataList::compatibility_iterator node = m_columns.Item( col ); wxCHECK_MSG( node, 0, _T("invalid column index") ); wxListHeaderData *column = node->GetData(); @@ -3798,11 +3746,58 @@ int wxListMainWindow::GetSelectedItemCount() const // item position/size // ---------------------------------------------------------------------------- +wxRect wxListMainWindow::GetViewRect() const +{ + wxASSERT_MSG( !HasFlag(wxLC_REPORT | wxLC_LIST), + _T("wxListCtrl::GetViewRect() only works in icon mode") ); + + // we need to find the longest/tallest label + wxCoord xMax = 0, + yMax = 0; + const int count = GetItemCount(); + if ( count ) + { + for ( int i = 0; i < count; i++ ) + { + wxRect r; + GetItemRect(i, r); + + wxCoord x = r.GetRight(), + y = r.GetBottom(); + + if ( x > xMax ) + xMax = x; + if ( y > yMax ) + yMax = y; + } + } + + // some fudge needed to make it look prettier + xMax += 2*EXTRA_BORDER_X; + yMax += 2*EXTRA_BORDER_Y; + + // account for the scrollbars if necessary + const wxSize sizeAll = GetClientSize(); + if ( xMax > sizeAll.x ) + yMax += wxSystemSettings::GetMetric(wxSYS_HSCROLL_Y); + if ( yMax > sizeAll.y ) + xMax += wxSystemSettings::GetMetric(wxSYS_VSCROLL_X); + + return wxRect(0, 0, xMax, yMax); +} + void wxListMainWindow::GetItemRect( long index, wxRect &rect ) const { wxCHECK_RET( index >= 0 && (size_t)index < GetItemCount(), _T("invalid index in GetItemRect") ); + // ensure that we're laid out, otherwise we could return nonsense + if ( m_dirty ) + { + wxConstCast(this, wxListMainWindow)-> + RecalculatePositions(TRUE /* no refresh */); + } + rect = GetLineRect((size_t)index); CalcScrolledPosition(rect.x, rect.y, &rect.x, &rect.y); @@ -3828,6 +3823,8 @@ void wxListMainWindow::RecalculatePositions(bool noRefresh) wxClientDC dc( this ); dc.SetFont( GetFont() ); + const size_t count = GetItemCount(); + int iconSpacing; if ( HasFlag(wxLC_ICON) ) iconSpacing = m_normal_spacing; @@ -3856,106 +3853,163 @@ void wxListMainWindow::RecalculatePositions(bool noRefresh) clientHeight; GetSize( &clientWidth, &clientHeight ); + const int lineHeight = GetLineHeight(); + if ( HasFlag(wxLC_REPORT) ) { - // all lines have the same height - int lineHeight = GetLineHeight(); - - // scroll one line per step - m_yScroll = lineHeight; - - size_t lineCount = GetItemCount(); - int entireHeight = lineCount*lineHeight + LINE_SPACING; + // all lines have the same height and we scroll one line per step + int entireHeight = count*lineHeight + LINE_SPACING; m_linesPerPage = clientHeight / lineHeight; ResetVisibleLinesRange(); - SetScrollbars( m_xScroll, m_yScroll, - GetHeaderWidth() / m_xScroll, - (entireHeight + m_yScroll - 1)/m_yScroll, + SetScrollbars( SCROLL_UNIT_X, lineHeight, + GetHeaderWidth() / SCROLL_UNIT_X, + (entireHeight + lineHeight - 1) / lineHeight, GetScrollPos(wxHORIZONTAL), GetScrollPos(wxVERTICAL), TRUE ); } else // !report { - // at first we try without any scrollbar. if the items don't - // fit into the window, we recalculate after subtracting an - // approximated 15 pt for the horizontal scrollbar - - int entireWidth = 0; - - for (int tries = 0; tries < 2; tries++) + // we have 3 different layout strategies: either layout all items + // horizontally/vertically (wxLC_ALIGN_XXX styles explicitly given) or + // to arrange them in top to bottom, left to right (don't ask me why + // not the other way round...) order + if ( HasFlag(wxLC_ALIGN_LEFT | wxLC_ALIGN_TOP) ) { - // We start with 4 for the border around all items - entireWidth = 4; + int x = EXTRA_BORDER_X; + int y = EXTRA_BORDER_Y; - if (tries == 1) - { - // Now we have decided that the items do not fit into the - // client area. Unfortunately, wxWindows sometimes thinks - // that it does fit and therefore NO horizontal scrollbar - // is inserted. This looks ugly, so we fudge here and make - // the calculated width bigger than was actually has been - // calculated. This ensures that wxScrolledWindows puts - // a scrollbar at the bottom of its client area. - entireWidth += SCROLL_UNIT_X; - } - - // Start at 2,2 so the text does not touch the border - int x = 2; - int y = 2; - int maxWidth = 0; - m_linesPerPage = 0; - int currentlyVisibleLines = 0; + wxCoord widthMax = 0; - size_t count = GetItemCount(); - for (size_t i = 0; i < count; i++) + size_t i; + for ( i = 0; i < count; i++ ) { - currentlyVisibleLines++; wxListLineData *line = GetLine(i); line->CalculateSize( &dc, iconSpacing ); - line->SetPosition( x, y, clientWidth, iconSpacing ); // Why clientWidth? (FIXME) + line->SetPosition( x, y, iconSpacing ); wxSize sizeLine = GetLineSize(i); - if ( maxWidth < sizeLine.x ) - maxWidth = sizeLine.x; + if ( HasFlag(wxLC_ALIGN_TOP) ) + { + if ( sizeLine.x > widthMax ) + widthMax = sizeLine.x; - y += sizeLine.y; - if (currentlyVisibleLines > m_linesPerPage) - m_linesPerPage = currentlyVisibleLines; + y += sizeLine.y; + } + else // wxLC_ALIGN_LEFT + { + x += sizeLine.x + MARGIN_BETWEEN_ROWS; + } + } - // Assume that the size of the next one is the same... (FIXME) - if ( y + sizeLine.y >= clientHeight ) + if ( HasFlag(wxLC_ALIGN_TOP) ) + { + // traverse the items again and tweak their sizes so that they are + // all the same in a row + for ( i = 0; i < count; i++ ) { - currentlyVisibleLines = 0; - y = 2; - x += maxWidth+6; - entireWidth += maxWidth+6; - maxWidth = 0; + wxListLineData *line = GetLine(i); + line->m_gi->ExtendWidth(widthMax); } + } - // We have reached the last item. - if ( i == count - 1 ) - entireWidth += maxWidth; - if ( (tries == 0) && (entireWidth+SCROLL_UNIT_X > clientWidth) ) + SetScrollbars + ( + SCROLL_UNIT_X, + lineHeight, + (x + SCROLL_UNIT_X) / SCROLL_UNIT_X, + (y + lineHeight) / lineHeight, + GetScrollPos( wxHORIZONTAL ), + GetScrollPos( wxVERTICAL ), + TRUE + ); + } + else // "flowed" arrangement, the most complicated case + { + // at first we try without any scrollbars, if the items don't fit into + // the window, we recalculate after subtracting the space taken by the + // scrollbar + + int entireWidth = 0; + + for (int tries = 0; tries < 2; tries++) + { + entireWidth = 2*EXTRA_BORDER_X; + + if (tries == 1) { - clientHeight -= 15; // We guess the scrollbar height. (FIXME) - m_linesPerPage = 0; - currentlyVisibleLines = 0; - break; + // Now we have decided that the items do not fit into the + // client area, so we need a scrollbar + entireWidth += SCROLL_UNIT_X; } - if ( i == count - 1 ) - tries = 1; // Everything fits, no second try required. + int x = EXTRA_BORDER_X; + int y = EXTRA_BORDER_Y; + int maxWidthInThisRow = 0; + + m_linesPerPage = 0; + int currentlyVisibleLines = 0; + + for (size_t i = 0; i < count; i++) + { + currentlyVisibleLines++; + wxListLineData *line = GetLine(i); + line->CalculateSize( &dc, iconSpacing ); + line->SetPosition( x, y, iconSpacing ); + + wxSize sizeLine = GetLineSize(i); + + if ( maxWidthInThisRow < sizeLine.x ) + maxWidthInThisRow = sizeLine.x; + + y += sizeLine.y; + if (currentlyVisibleLines > m_linesPerPage) + m_linesPerPage = currentlyVisibleLines; + + if ( y + sizeLine.y >= clientHeight ) + { + currentlyVisibleLines = 0; + y = EXTRA_BORDER_Y; + maxWidthInThisRow += MARGIN_BETWEEN_ROWS; + x += maxWidthInThisRow; + entireWidth += maxWidthInThisRow; + maxWidthInThisRow = 0; + } + + // We have reached the last item. + if ( i == count - 1 ) + entireWidth += maxWidthInThisRow; + + if ( (tries == 0) && + (entireWidth + SCROLL_UNIT_X > clientWidth) ) + { + clientHeight -= wxSystemSettings:: + GetMetric(wxSYS_HSCROLL_Y); + m_linesPerPage = 0; + break; + } + + if ( i == count - 1 ) + tries = 1; // Everything fits, no second try required. + } } - } - int scroll_pos = GetScrollPos( wxHORIZONTAL ); - SetScrollbars( m_xScroll, m_yScroll, (entireWidth+SCROLL_UNIT_X) / m_xScroll, 0, scroll_pos, 0, TRUE ); + SetScrollbars + ( + SCROLL_UNIT_X, + lineHeight, + (entireWidth + SCROLL_UNIT_X) / SCROLL_UNIT_X, + 0, + GetScrollPos( wxHORIZONTAL ), + 0, + TRUE + ); + } } if ( !noRefresh ) @@ -4078,12 +4132,25 @@ void wxListMainWindow::DeleteItem( long lindex ) void wxListMainWindow::DeleteColumn( int col ) { - wxListHeaderDataList::Node *node = m_columns.Item( col ); + wxListHeaderDataList::compatibility_iterator node = m_columns.Item( col ); wxCHECK_RET( node, wxT("invalid column index in DeleteColumn()") ); m_dirty = TRUE; - m_columns.DeleteNode( node ); + delete node->GetData(); + m_columns.Erase( node ); + + if ( !IsVirtual() ) + { + // update all the items + for ( size_t i = 0; i < m_lines.GetCount(); i++ ) + { + wxListLineData * const line = GetLine(i); + wxListItemDataList::compatibility_iterator n = line->m_items.Item( col ); + delete n->GetData(); + line->m_items.Erase(n); + } + } // invalidate it as it has to be recalculated m_headerWidth = 0; @@ -4132,7 +4199,7 @@ void wxListMainWindow::DeleteAllItems() void wxListMainWindow::DeleteEverything() { - m_columns.Clear(); + WX_CLEAR_LIST(wxListHeaderDataList, m_columns); DeleteAllItems(); } @@ -4240,18 +4307,39 @@ void wxListMainWindow::InsertItem( wxListItem &item ) m_dirty = TRUE; + #if 0 + // this is unused variable int mode = 0; + #endif if ( HasFlag(wxLC_REPORT) ) { + #if 0 + // this is unused variable mode = wxLC_REPORT; + #endif ResetVisibleLinesRange(); } else if ( HasFlag(wxLC_LIST) ) + #if 0 + // this is unused variable mode = wxLC_LIST; + #else + {} + #endif else if ( HasFlag(wxLC_ICON) ) + #if 0 + // this is unused variable mode = wxLC_ICON; + #else + {} + #endif else if ( HasFlag(wxLC_SMALL_ICON) ) + #if 0 + // this is unused variable mode = wxLC_ICON; // no typo + #else + {} + #endif else { wxFAIL_MSG( _T("unknown mode") ); @@ -4265,6 +4353,14 @@ void wxListMainWindow::InsertItem( wxListItem &item ) m_dirty = TRUE; + // If an item is selected at or below the point of insertion, we need to + // increment the member variables because the current row's index has gone + // up by one + if ( HasCurrent() && m_current >= id ) + { + m_current++; + } + SendNotify(id, wxEVT_COMMAND_LIST_INSERT_ITEM); RefreshLines(id, GetItemCount() - 1); @@ -4277,10 +4373,12 @@ void wxListMainWindow::InsertColumn( long col, wxListItem &item ) { if (item.m_width == wxLIST_AUTOSIZE_USEHEADER) item.m_width = GetTextLength( item.m_text ); + wxListHeaderData *column = new wxListHeaderData( item ); - if ((col >= 0) && (col < (int)m_columns.GetCount())) + bool insert = (col >= 0) && ((size_t)col < m_columns.GetCount()); + if ( insert ) { - wxListHeaderDataList::Node *node = m_columns.Item( col ); + wxListHeaderDataList::compatibility_iterator node = m_columns.Item( col ); m_columns.Insert( node, column ); } else @@ -4288,6 +4386,20 @@ void wxListMainWindow::InsertColumn( long col, wxListItem &item ) m_columns.Append( column ); } + if ( !IsVirtual() ) + { + // update all the items + for ( size_t i = 0; i < m_lines.GetCount(); i++ ) + { + wxListLineData * const line = GetLine(i); + wxListItemData * const data = new wxListItemData(this); + if ( insert ) + line->m_items.Insert(col, data); + else + line->m_items.Append(data); + } + } + // invalidate it as it has to be recalculated m_headerWidth = 0; } @@ -4404,7 +4516,6 @@ IMPLEMENT_DYNAMIC_CLASS(wxGenericListCtrl, wxControl) BEGIN_EVENT_TABLE(wxGenericListCtrl,wxControl) EVT_SIZE(wxGenericListCtrl::OnSize) - EVT_IDLE(wxGenericListCtrl::OnIdle) END_EVENT_TABLE() wxGenericListCtrl::wxGenericListCtrl() @@ -4419,6 +4530,7 @@ wxGenericListCtrl::wxGenericListCtrl() m_mainWin = (wxListMainWindow*) NULL; m_headerWin = (wxListHeaderWindow*) NULL; + m_headerHeight = 0; } wxGenericListCtrl::~wxGenericListCtrl() @@ -4431,15 +4543,38 @@ wxGenericListCtrl::~wxGenericListCtrl() delete m_imageListState; } +void wxGenericListCtrl::CalculateAndSetHeaderHeight() +{ + if ( m_headerWin ) + { + // we use 'g' to get the descent, too + int w, h, d; + m_headerWin->GetTextExtent(wxT("Hg"), &w, &h, &d); + h += d + 2 * HEADER_OFFSET_Y + EXTRA_HEIGHT; + + // only update if changed + if ( h != m_headerHeight ) + { + m_headerHeight = h; + + m_headerWin->SetSize(m_headerWin->GetSize().x, m_headerHeight); + + if ( HasFlag(wxLC_REPORT) && !HasFlag(wxLC_NO_HEADER) ) + ResizeReportView(TRUE); + } + } +} + void wxGenericListCtrl::CreateHeaderWindow() { m_headerWin = new wxListHeaderWindow ( this, -1, m_mainWin, wxPoint(0, 0), - wxSize(GetClientSize().x, HEADER_HEIGHT), + wxSize(GetClientSize().x, m_headerHeight), wxTAB_TRAVERSAL ); + CalculateAndSetHeaderHeight(); } bool wxGenericListCtrl::Create(wxWindow *parent, @@ -4662,11 +4797,16 @@ bool wxGenericListCtrl::SetItemData( long item, long data ) return TRUE; } +wxRect wxGenericListCtrl::GetViewRect() const +{ + return m_mainWin->GetViewRect(); +} + bool wxGenericListCtrl::GetItemRect( long item, wxRect &rect, int WXUNUSED(code) ) const { m_mainWin->GetItemRect( item, rect ); if ( m_mainWin->HasHeader() ) - rect.y += HEADER_HEIGHT + 1; + rect.y += m_headerHeight + 1; return TRUE; } @@ -4696,6 +4836,13 @@ void wxGenericListCtrl::SetItemSpacing( int spacing, bool isSmall ) m_mainWin->SetItemSpacing( spacing, isSmall ); } +wxSize wxGenericListCtrl::GetItemSpacing() const +{ + const int spacing = m_mainWin->GetItemSpacing(HasFlag(wxLC_SMALL_ICON)); + + return wxSize(spacing, spacing); +} + int wxGenericListCtrl::GetItemSpacing( bool isSmall ) const { return m_mainWin->GetItemSpacing( isSmall ); @@ -4998,8 +5145,8 @@ void wxGenericListCtrl::ResizeReportView(bool showHeader) if ( showHeader ) { - m_headerWin->SetSize( 0, 0, cw, HEADER_HEIGHT ); - m_mainWin->SetSize( 0, HEADER_HEIGHT + 1, cw, ch - HEADER_HEIGHT - 1 ); + m_headerWin->SetSize( 0, 0, cw, m_headerHeight ); + m_mainWin->SetSize( 0, m_headerHeight + 1, cw, ch - m_headerHeight - 1 ); } else // no header window { @@ -5007,9 +5154,9 @@ void wxGenericListCtrl::ResizeReportView(bool showHeader) } } -void wxGenericListCtrl::OnIdle( wxIdleEvent & event ) +void wxGenericListCtrl::OnInternalIdle() { - event.Skip(); + wxWindow::OnInternalIdle(); // do it only if needed if ( !m_mainWin->m_dirty ) @@ -5066,8 +5213,11 @@ bool wxGenericListCtrl::SetFont( const wxFont &font ) if (m_headerWin) { m_headerWin->SetFont( font ); + CalculateAndSetHeaderHeight(); } + Refresh(); + return TRUE; } @@ -5142,7 +5292,8 @@ int wxGenericListCtrl::OnGetItemImage(long WXUNUSED(item)) const return -1; } -wxListItemAttr *wxGenericListCtrl::OnGetItemAttr(long item) const +wxListItemAttr * +wxGenericListCtrl::OnGetItemAttr(long WXUNUSED_UNLESS_DEBUG(item)) const { wxASSERT_MSG( item >= 0 && item < GetItemCount(), _T("invalid item index in OnGetItemAttr()") ); @@ -5168,6 +5319,57 @@ void wxGenericListCtrl::RefreshItems(long itemFrom, long itemTo) m_mainWin->RefreshLines(itemFrom, itemTo); } +/* + * Generic wxListCtrl is more or less a container for two other + * windows which drawings are done upon. These are namely + * 'm_headerWin' and 'm_mainWin'. + * Here we override 'virtual wxWindow::Refresh()' to mimic the + * behaviour wxListCtrl has under wxMSW. + */ +void wxGenericListCtrl::Refresh(bool eraseBackground, const wxRect *rect) +{ + if (!rect) + { + // The easy case, no rectangle specified. + if (m_headerWin) + m_headerWin->Refresh(eraseBackground); + + if (m_mainWin) + m_mainWin->Refresh(eraseBackground); + } + else + { + // Refresh the header window + if (m_headerWin) + { + wxRect rectHeader = m_headerWin->GetRect(); + rectHeader.Intersect(*rect); + if (rectHeader.GetWidth() && rectHeader.GetHeight()) + { + int x, y; + m_headerWin->GetPosition(&x, &y); + rectHeader.Offset(-x, -y); + m_headerWin->Refresh(eraseBackground, &rectHeader); + } + + } + + // Refresh the main window + if (m_mainWin) + { + wxRect rectMain = m_mainWin->GetRect(); + rectMain.Intersect(*rect); + if (rectMain.GetWidth() && rectMain.GetHeight()) + { + int x, y; + m_mainWin->GetPosition(&x, &y); + rectMain.Offset(-x, -y); + m_mainWin->Refresh(eraseBackground, &rectMain); + } + } + } +} + void wxGenericListCtrl::Freeze() { m_mainWin->Freeze();