X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/bf9b6266faaa6534b75e5282aab58f1476eecbaa..10207b728dcc7e3dbb8acaf70cfb2d0cecbc78b2:/src/generic/listctrl.cpp diff --git a/src/generic/listctrl.cpp b/src/generic/listctrl.cpp index 93b43f1529..35d5d712b8 100644 --- a/src/generic/listctrl.cpp +++ b/src/generic/listctrl.cpp @@ -9,32 +9,10 @@ ///////////////////////////////////////////////////////////////////////////// /* - TODO for better virtual list control support: + TODO - 1. less dumb line caching, we should cache at least all those visible - in the control itself and probably twice as many (we might also need to - cache the first one always for geometry calculations?) - - +2. storing selections: we can't use an array to store the selected indices - like right now as selecting all in a control with 1000000 items is not - doable like this - instead, store selections as collection of individual - items and ranges - - => wxSelectionStore - - 3. we need to implement searching/sorting somehow - - 4. the idea of storing the line index in the line itself is really stupid, - we shouldn't need it - but for this we have to get rid of all calles to - wxListLineData::GetFoo() and replace them with something like - if ( IsVirtual() - ... we have it ourselves ... - else - line->GetFoo(); - - => done - - 5. attributes support: we need OnGetItemAttr() as well! + 1. we need to implement searching/sorting for virtual controls somehow + ?2. when changing selection the lines are refreshed twice */ // ============================================================================ @@ -87,6 +65,10 @@ DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_DESELECTED) DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_KEY_DOWN) DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_INSERT_ITEM) DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_CLICK) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_RIGHT_CLICK) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_BEGIN_DRAG) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_DRAGGING) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_END_DRAG) 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) @@ -121,6 +103,9 @@ static const int AUTOSIZE_COL_MARGIN = 10; static const int WIDTH_COL_DEFAULT = 80; static const int WIDTH_COL_MIN = 10; +// the space between the image and the text in the report mode +static const int IMAGE_MARGIN_IN_REPORT_MODE = 5; + // ============================================================================ // private classes // ============================================================================ @@ -279,16 +264,6 @@ protected: class WXDLLEXPORT wxListHeaderData : public wxObject { -protected: - long m_mask; - int m_image; - wxString m_text; - int m_format; - int m_width; - int m_xpos, - m_ypos; - int m_height; - public: wxListHeaderData(); wxListHeaderData( const wxListItem &info ); @@ -310,8 +285,18 @@ public: int GetWidth() const; int GetFormat() const; +protected: + long m_mask; + int m_image; + wxString m_text; + int m_format; + int m_width; + int m_xpos, + m_ypos; + int m_height; + private: - DECLARE_DYNAMIC_CLASS(wxListHeaderData); + void Init(); }; //----------------------------------------------------------------------------- @@ -454,7 +439,6 @@ protected: public: wxListHeaderWindow(); - virtual ~wxListHeaderWindow(); wxListHeaderWindow( wxWindow *win, wxWindowID id, @@ -464,6 +448,8 @@ public: long style = 0, const wxString &name = "wxlistctrlcolumntitles" ); + virtual ~wxListHeaderWindow(); + void DoDrawRect( wxDC *dc, int x, int y, int w, int h ); void DrawCurrent(); void AdjustDC(wxDC& dc); @@ -476,6 +462,9 @@ public: bool m_dirty; private: + // common part of all ctors + void Init(); + DECLARE_DYNAMIC_CLASS(wxListHeaderWindow) DECLARE_EVENT_TABLE() }; @@ -584,6 +573,9 @@ public: void RefreshLine( size_t line ); void RefreshLines( size_t lineFrom, size_t lineTo ); + // refresh all selected items + void RefreshSelected(); + // refresh all lines below the given one: the difference with // RefreshLines() is that the index here might not be a valid one (happens // when the last line is deleted) @@ -719,6 +711,12 @@ public: // get the y position of the given line (only for report view) wxCoord GetLineY(size_t line) const; + // get the brush to use for the item highlighting + wxBrush *GetHighlightBrush() const + { + return m_hasFocus ? m_highlightBrush : m_highlightUnfocusedBrush; + } + //protected: // the array of all line objects for a non virtual list control wxListLineDataArray m_lines; @@ -743,7 +741,6 @@ public: // call bool m_dirty; - wxBrush *m_highlightBrush; wxColour *m_highlightColour; int m_xScroll, m_yScroll; @@ -842,6 +839,10 @@ private: size_t m_lineFrom, m_lineTo; + // the brushes to use for item highlighting when we do/don't have focus + wxBrush *m_highlightBrush, + *m_highlightUnfocusedBrush; + DECLARE_DYNAMIC_CLASS(wxListMainWindow); DECLARE_EVENT_TABLE() }; @@ -1165,12 +1166,10 @@ void wxListItemData::GetItem( wxListItem &info ) const // wxListHeaderData //----------------------------------------------------------------------------- -IMPLEMENT_DYNAMIC_CLASS(wxListHeaderData,wxObject); - -wxListHeaderData::wxListHeaderData() +void wxListHeaderData::Init() { m_mask = 0; - m_image = 0; + m_image = -1; m_format = 0; m_width = 0; m_xpos = 0; @@ -1178,22 +1177,33 @@ wxListHeaderData::wxListHeaderData() m_height = 0; } +wxListHeaderData::wxListHeaderData() +{ + Init(); +} + wxListHeaderData::wxListHeaderData( const wxListItem &item ) { + Init(); + SetItem( item ); - m_xpos = 0; - m_ypos = 0; - m_height = 0; } void wxListHeaderData::SetItem( const wxListItem &item ) { m_mask = item.m_mask; - m_text = item.m_text; - m_image = item.m_image; - m_format = item.m_format; - SetWidth(item.m_width); + if ( m_mask & wxLIST_MASK_TEXT ) + m_text = item.m_text; + + if ( m_mask & wxLIST_MASK_IMAGE ) + m_image = item.m_image; + + if ( m_mask & wxLIST_MASK_FORMAT ) + m_format = item.m_format; + + if ( m_mask & wxLIST_MASK_WIDTH ) + SetWidth(item.m_width); } void wxListHeaderData::SetPosition( int x, int y ) @@ -1212,7 +1222,7 @@ void wxListHeaderData::SetWidth( int w ) m_width = w; if (m_width < 0) m_width = WIDTH_COL_DEFAULT; - if (m_width < WIDTH_COL_MIN) + else if (m_width < WIDTH_COL_MIN) m_width = WIDTH_COL_MIN; } @@ -1223,7 +1233,7 @@ void wxListHeaderData::SetFormat( int format ) bool wxListHeaderData::HasImage() const { - return (m_image != 0); + return m_image != -1; } bool wxListHeaderData::IsHit( int x, int y ) const @@ -1231,7 +1241,7 @@ bool wxListHeaderData::IsHit( int x, int y ) const return ((x >= m_xpos) && (x <= m_xpos+m_width) && (y >= m_ypos) && (y <= m_ypos+m_height)); } -void wxListHeaderData::GetItem( wxListItem &item ) +void wxListHeaderData::GetItem( wxListItem& item ) { item.m_mask = m_mask; item.m_text = m_text; @@ -1604,7 +1614,7 @@ bool wxListLineData::SetAttributes(wxDC *dc, { if ( highlighted ) { - dc->SetBrush( *m_owner->m_highlightBrush ); + dc->SetBrush( *m_owner->GetHighlightBrush() ); } else { @@ -1644,6 +1654,8 @@ void wxListLineData::Draw( wxDC *dc ) if (item->HasText()) { wxRect rectLabel = m_gi->m_rectLabel; + + wxDCClipper clipper(*dc, rectLabel); dc->DrawText( item->GetText(), rectLabel.x, rectLabel.y ); } } @@ -1653,10 +1665,6 @@ void wxListLineData::DrawInReportMode( wxDC *dc, const wxRect& rectHL, bool highlighted ) { - // use our own flag if we maintain it - if ( !IsVirtual() ) - highlighted = m_highlighted; - // TODO: later we should support setting different attributes for // different columns - to do it, just add "col" argument to // GetAttr() and move these lines into the loop below @@ -1677,27 +1685,29 @@ void wxListLineData::DrawInReportMode( wxDC *dc, { wxListItemData *item = node->GetData(); + int width = m_owner->GetColumnWidth(col++); int xOld = x; + x += width; if ( item->HasImage() ) { int ix, iy; - m_owner->DrawImage( item->GetImage(), dc, x, y ); + m_owner->DrawImage( item->GetImage(), dc, xOld, y ); m_owner->GetImageSize( item->GetImage(), ix, iy ); - x += ix + 5; // FIXME: what is "5"? - } - int width = m_owner->GetColumnWidth(col++); + ix += IMAGE_MARGIN_IN_REPORT_MODE; - wxDCClipper clipper(*dc, x, y, width, rect.height); + xOld += ix; + width -= ix; + } + + wxDCClipper clipper(*dc, xOld, y, width, rect.height); if ( item->HasText() ) { - dc->DrawText( item->GetText(), x, y ); + dc->DrawText( item->GetText(), xOld, y ); } - x = xOld + width; - node = node->GetNext(); } } @@ -1731,30 +1741,39 @@ BEGIN_EVENT_TABLE(wxListHeaderWindow,wxWindow) EVT_SET_FOCUS (wxListHeaderWindow::OnSetFocus) END_EVENT_TABLE() -wxListHeaderWindow::wxListHeaderWindow( void ) +void wxListHeaderWindow::Init() { - m_owner = (wxListMainWindow *) NULL; m_currentCursor = (wxCursor *) NULL; - m_resizeCursor = (wxCursor *) NULL; m_isDragging = FALSE; + m_dirty = FALSE; +} + +wxListHeaderWindow::wxListHeaderWindow() +{ + Init(); + + m_owner = (wxListMainWindow *) NULL; + m_resizeCursor = (wxCursor *) NULL; } -wxListHeaderWindow::wxListHeaderWindow( wxWindow *win, wxWindowID id, wxListMainWindow *owner, - const wxPoint &pos, const wxSize &size, - long style, const wxString &name ) : - wxWindow( win, id, pos, size, style, name ) +wxListHeaderWindow::wxListHeaderWindow( wxWindow *win, + wxWindowID id, + wxListMainWindow *owner, + const wxPoint& pos, + const wxSize& size, + long style, + const wxString &name ) + : wxWindow( win, id, pos, size, style, name ) { + Init(); + m_owner = owner; -// m_currentCursor = wxSTANDARD_CURSOR; - m_currentCursor = (wxCursor *) NULL; m_resizeCursor = new wxCursor( wxCURSOR_SIZEWE ); - m_isDragging = FALSE; - m_dirty = FALSE; SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE ) ); } -wxListHeaderWindow::~wxListHeaderWindow( void ) +wxListHeaderWindow::~wxListHeaderWindow() { delete m_resizeCursor; } @@ -1860,25 +1879,53 @@ void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) int numColumns = m_owner->GetColumnCount(); wxListItem item; - for (int i = 0; i < numColumns; i++) + for ( int i = 0; i < numColumns && x < w; i++ ) { m_owner->GetColumn( i, item ); int wCol = item.m_width; - int cw = wCol - 2; // the width of the rect to draw - int xEnd = x + wCol; + // the width of the rect to draw: make it smaller to fit entirely + // inside the column rect + int cw = wCol - 2; dc.SetPen( *wxWHITE_PEN ); DoDrawRect( &dc, x, HEADER_OFFSET_Y, cw, h-2 ); - dc.SetClippingRegion( x, HEADER_OFFSET_Y, cw-5, h-4 ); - dc.DrawText( item.GetText(), x + EXTRA_WIDTH, HEADER_OFFSET_Y + EXTRA_HEIGHT ); - dc.DestroyClippingRegion(); - x += wCol; - if (xEnd > w+5) - break; + // if we have an image, draw it on the right of the label + int image = item.m_image; + if ( image != -1 ) + { + wxImageList *imageList = m_owner->m_small_image_list; + if ( imageList ) + { + int ix, iy; + imageList->GetSize(image, ix, iy); + + imageList->Draw + ( + image, + dc, + x + cw - ix - 1, + HEADER_OFFSET_Y + (h - 4 - iy)/2, + wxIMAGELIST_DRAW_TRANSPARENT + ); + + cw -= ix + 2; + } + //else: ignore the column image + } + + // draw the text clipping it so that it doesn't overwrite the column + // boundary + wxDCClipper clipper(dc, x, HEADER_OFFSET_Y, cw, h - 4 ); + + dc.DrawText( item.GetText(), + x + EXTRA_WIDTH, HEADER_OFFSET_Y + EXTRA_HEIGHT ); + + x += wCol; } + dc.EndDrawing(); } @@ -1978,20 +2025,31 @@ void wxListHeaderWindow::OnMouse( wxMouseEvent &event ) m_minX = xpos; } - if (event.LeftDown()) + if (event.LeftDown() || event.RightUp()) { - if (hit_border) + if (hit_border && event.LeftDown()) { m_isDragging = TRUE; m_currentX = x; DrawCurrent(); CaptureMouse(); } - else + else // click on a column { wxWindow *parent = GetParent(); - wxListEvent le( wxEVT_COMMAND_LIST_COL_CLICK, parent->GetId() ); + wxListEvent le( event.LeftDown() + ? wxEVT_COMMAND_LIST_COL_CLICK + : wxEVT_COMMAND_LIST_COL_RIGHT_CLICK, + parent->GetId() ); le.SetEventObject( parent ); + le.m_pointDrag = event.GetPosition(); + + // the position should be relative to the parent window, not + // this one for compatibility with MSW and common sense: the + // user code doesn't know anything at all about this header + // window, so why should it get positions relative to it? + le.m_pointDrag.y -= GetSize().y; + le.m_col = m_column; parent->GetEventHandler()->ProcessEvent( le ); } @@ -2189,7 +2247,8 @@ wxListMainWindow::wxListMainWindow() { Init(); - m_highlightBrush = (wxBrush *) NULL; + m_highlightBrush = + m_highlightUnfocusedBrush = (wxBrush *) NULL; m_xScroll = m_yScroll = 0; @@ -2206,7 +2265,24 @@ wxListMainWindow::wxListMainWindow( wxWindow *parent, { Init(); - m_highlightBrush = new wxBrush( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHT), wxSOLID ); + m_highlightBrush = new wxBrush + ( + wxSystemSettings::GetSystemColour + ( + wxSYS_COLOUR_HIGHLIGHT + ), + wxSOLID + ); + + m_highlightUnfocusedBrush = new wxBrush + ( + wxSystemSettings::GetSystemColour + ( + wxSYS_COLOUR_BTNSHADOW + ), + wxSOLID + ); + wxSize sz = size; sz.y = 25; @@ -2221,6 +2297,7 @@ wxListMainWindow::~wxListMainWindow() DoDeleteAllItems(); delete m_highlightBrush; + delete m_highlightUnfocusedBrush; delete m_renameTimer; } @@ -2347,6 +2424,8 @@ wxRect wxListMainWindow::GetLineHighlightRect(size_t line) const long wxListMainWindow::HitTestLine(size_t line, int x, int y) const { + wxASSERT_MSG( line < GetItemCount(), _T("invalid line in HitTestLine") ); + wxListLineData *ld = GetLine(line); if ( ld->HasImage() && GetLineIconRect(line).Inside(x, y) ) @@ -2428,7 +2507,7 @@ bool wxListMainWindow::HighlightLine( size_t line, bool highlight ) else // !virtual { wxListLineData *ld = GetLine(line); - wxCHECK_MSG( ld, FALSE, _T("invalid index in IsHighlighted") ); + wxCHECK_MSG( ld, FALSE, _T("invalid index in HighlightLine") ); changed = ld->Highlight(highlight); } @@ -2444,6 +2523,15 @@ bool wxListMainWindow::HighlightLine( size_t line, bool highlight ) void wxListMainWindow::RefreshLine( size_t line ) { + if ( HasFlag(wxLC_REPORT) ) + { + size_t visibleFrom, visibleTo; + GetVisibleLinesRange(&visibleFrom, &visibleTo); + + if ( line < visibleFrom || line > visibleTo ) + return; + } + wxRect rect = GetLineRect(line); CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y ); @@ -2515,6 +2603,65 @@ void wxListMainWindow::RefreshAfter( size_t lineFrom ) } } +void wxListMainWindow::RefreshSelected() +{ + if ( IsEmpty() ) + return; + + size_t from, to; + if ( InReportView() ) + { + GetVisibleLinesRange(&from, &to); + } + else // !virtual + { + from = 0; + to = GetItemCount() - 1; + } + + // VZ: this code would work fine if wxGTK wxWindow::Refresh() were + // reasonable, i.e. if it only generated one expose event for + // several calls to it - as it is, each Refresh() results in a + // repaint which provokes flicker too horrible to be seen + // + // when/if wxGTK is fixed, this code should be restored as normally it + // should generate _less_ flicker than the version below +#ifndef __WXGTK__ + if ( HasCurrent() && m_current >= from && m_current <= to ) + { + RefreshLine(m_current); + } + + for ( size_t line = from; line <= to; line++ ) + { + // NB: the test works as expected even if m_current == -1 + if ( line != m_current && IsHighlighted(line) ) + { + RefreshLine(line); + } + } +#else // __WXGTK__ + size_t selMin = (size_t)-1, + selMax = 0; + + for ( size_t line = from; line <= to; line++ ) + { + if ( IsHighlighted(line) || (line == m_current) ) + { + if ( line < selMin ) + selMin = line; + if ( line > selMax ) + selMax = line; + } + } + + if ( selMin != (size_t)-1 ) + { + RefreshLines(selMin, selMax); + } +#endif // !__WXGTK__/__WXGTK__ +} + void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) { // Note: a wxPaintDC must be constructed even if no drawing is @@ -2635,15 +2782,21 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) } } - if ( HasCurrent() && m_hasFocus ) + if ( HasCurrent() ) { + // don't draw rect outline under Max if we already have the background + // color but under other platforms only draw it if we do: it is a bit + // silly to draw "focus rect" if we don't have focus! #ifdef __WXMAC__ - // no rect outline, we already have the background color -#else - dc.SetPen( *wxBLACK_PEN ); - dc.SetBrush( *wxTRANSPARENT_BRUSH ); - dc.DrawRectangle( GetLineHighlightRect(m_current) ); -#endif + if ( !m_hasFocus ) +#else // !__WXMAC__ + if ( m_hasFocus ) +#endif // __WXMAC__/!__WXMAC__ + { + dc.SetPen( *wxBLACK_PEN ); + dc.SetBrush( *wxTRANSPARENT_BRUSH ); + dc.DrawRectangle( GetLineHighlightRect(m_current) ); + } } dc.EndDrawing(); @@ -2680,7 +2833,11 @@ void wxListMainWindow::SendNotify( size_t line, if ( point != wxDefaultPosition ) le.m_pointDrag = point; - if ( command != wxEVT_COMMAND_LIST_DELETE_ITEM ) + // don't try to get the line info for virtual list controls: the main + // program has it anyhow and if we did it would result in accessing all + // the lines, even those which are not visible now and this is precisely + // what we're trying to avoid + if ( !IsVirtual() && (command != wxEVT_COMMAND_LIST_DELETE_ITEM) ) { GetLine(line)->GetItem( 0, le.m_item ); } @@ -2821,7 +2978,12 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event ) if (event.Dragging()) { if (m_dragCount == 0) - m_dragStart = wxPoint(x,y); + { + // we have to report the raw, physical coords as we want to be + // able to call HitTest(event.m_pointDrag) from the user code to + // get the item being dragged + m_dragStart = event.GetPosition(); + } m_dragCount++; @@ -3186,11 +3348,16 @@ void wxListMainWindow::OnChar( wxKeyEvent &event ) le.m_itemIndex = m_current; GetLine(m_current)->GetItem( 0, le.m_item ); GetParent()->GetEventHandler()->ProcessEvent( le ); + + if ( IsHighlighted(m_current) ) + { + // don't unselect the item in single selection mode + break; + } + //else: select it in ReverseHighlight() below if unselected } - else - { - ReverseHighlight(m_current); - } + + ReverseHighlight(m_current); break; case WXK_RETURN: @@ -3220,12 +3387,18 @@ extern wxWindow *g_focusWindow; void wxListMainWindow::OnSetFocus( wxFocusEvent &WXUNUSED(event) ) { - m_hasFocus = TRUE; + // 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 + // it + if ( !m_hasFocus ) + { + m_hasFocus = TRUE; - if ( HasCurrent() ) - RefreshLine( m_current ); + RefreshSelected(); + } - if (!GetParent()) + if ( !GetParent() ) return; #ifdef __WXGTK__ @@ -3241,8 +3414,7 @@ void wxListMainWindow::OnKillFocus( wxFocusEvent &WXUNUSED(event) ) { m_hasFocus = FALSE; - if ( HasCurrent() ) - RefreshLine( m_current ); + RefreshSelected(); } void wxListMainWindow::DrawImage( int index, wxDC *dc, int x, int y ) @@ -3379,6 +3551,9 @@ void wxListMainWindow::SetColumnWidth( int col, int width ) _T("SetColumnWidth() can only be called in report mode.") ); m_dirty = TRUE; + wxListHeaderWindow *headerWin = GetListCtrl()->m_headerWin; + if ( headerWin ) + headerWin->m_dirty = TRUE; wxListHeaderDataList::Node *node = m_columns.Item( col ); wxCHECK_RET( node, _T("no column?") ); @@ -3511,8 +3686,9 @@ void wxListMainWindow::SetItemState( long litem, long state, long stateMask ) _T("invalid list ctrl item index in SetItem") ); size_t oldCurrent = m_current; - size_t item = (size_t)litem; // sdafe because of the check above + size_t item = (size_t)litem; // safe because of the check above + // do we need to change the focus? if ( stateMask & wxLIST_STATE_FOCUSED ) { if ( state & wxLIST_STATE_FOCUSED ) @@ -3524,9 +3700,13 @@ void wxListMainWindow::SetItemState( long litem, long state, long stateMask ) m_current = item; OnFocusLine( m_current ); - if ( IsSingleSel() && (oldCurrent != (size_t)-1) ) + if ( oldCurrent != (size_t)-1 ) { - HighlightLine(oldCurrent, FALSE); + if ( IsSingleSel() ) + { + HighlightLine(oldCurrent, FALSE); + } + RefreshLine(oldCurrent); } @@ -3540,10 +3720,13 @@ void wxListMainWindow::SetItemState( long litem, long state, long stateMask ) { OnUnfocusLine( m_current ); m_current = (size_t)-1; + + RefreshLine( oldCurrent ); } } } + // do we need to change the selection state? if ( stateMask & wxLIST_STATE_SELECTED ) { bool on = (state & wxLIST_STATE_SELECTED) != 0; @@ -3804,7 +3987,7 @@ void wxListMainWindow::RefreshAll() Refresh(); wxListHeaderWindow *headerWin = GetListCtrl()->m_headerWin; - if ( headerWin ) + if ( headerWin && headerWin->m_dirty ) { headerWin->m_dirty = FALSE; headerWin->Refresh(); @@ -3904,6 +4087,7 @@ void wxListMainWindow::DeleteItem( long lindex ) m_lines.RemoveAt( index ); } + // we need to refresh the (vert) scrollbar as the number of items changed m_dirty = TRUE; SendNotify( index, wxEVT_COMMAND_LIST_DELETE_ITEM ); @@ -3982,8 +4166,6 @@ void wxListMainWindow::EnsureVisible( long index ) // been added and its position is not known yet if ( m_dirty ) { - m_dirty = FALSE; - RecalculatePositions(TRUE /* no refresh */); } @@ -4031,18 +4213,22 @@ long wxListMainWindow::HitTest( int x, int y, int &flags ) { CalcUnscrolledPosition( x, y, &x, &y ); + size_t count = GetItemCount(); + if ( HasFlag(wxLC_REPORT) ) { size_t current = y / GetLineHeight(); - flags = HitTestLine(current, x, y); - if ( flags ) - return current; + if ( current < count ) + { + flags = HitTestLine(current, x, y); + if ( flags ) + return current; + } } else // !report { // TODO: optimize it too! this is less simple than for report view but // enumerating all items is still not a way to do it!! - size_t count = GetItemCount(); for ( size_t current = 0; current < count; current++ ) { flags = HitTestLine(current, x, y); @@ -4227,17 +4413,9 @@ IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject) wxListItem::wxListItem() { - m_mask = 0; - m_itemId = 0; - m_col = 0; - m_state = 0; - m_stateMask = 0; - m_image = 0; - m_data = 0; - m_format = wxLIST_FORMAT_CENTRE; - m_width = 0; - m_attr = NULL; + + Clear(); } void wxListItem::Clear() @@ -4247,11 +4425,11 @@ void wxListItem::Clear() m_col = 0; m_state = 0; m_stateMask = 0; - m_image = 0; + m_image = -1; m_data = 0; m_format = wxLIST_FORMAT_CENTRE; m_width = 0; - m_text = _T(""); + m_text.clear(); ClearAttributes(); } @@ -4724,7 +4902,7 @@ bool wxListCtrl::DeleteAllColumns() { size_t count = m_mainWin->m_columns.GetCount(); for ( size_t n = 0; n < count; n++ ) - DeleteColumn(n); + DeleteColumn(0); return TRUE; }