X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c1c4c5516c6e6567302f8b02444255d2a37ac114..b838cfc9151aea38402ad2b1ba5d2f97cf94e973:/src/generic/listctrl.cpp?ds=sidebyside diff --git a/src/generic/listctrl.cpp b/src/generic/listctrl.cpp index e4fc11143e..3ca9aa51ac 100644 --- a/src/generic/listctrl.cpp +++ b/src/generic/listctrl.cpp @@ -9,9 +9,10 @@ ///////////////////////////////////////////////////////////////////////////// /* - TODO for better virtual list control support: + TODO - 1. we need to implement searching/sorting somehow + 1. we need to implement searching/sorting for virtual controls somehow + 2. when changing selection the lines are refreshed twice */ // ============================================================================ @@ -98,6 +99,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 // ============================================================================ @@ -561,6 +565,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) @@ -696,6 +703,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; @@ -720,7 +733,6 @@ public: // call bool m_dirty; - wxBrush *m_highlightBrush; wxColour *m_highlightColour; int m_xScroll, m_yScroll; @@ -819,6 +831,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() }; @@ -1581,7 +1597,7 @@ bool wxListLineData::SetAttributes(wxDC *dc, { if ( highlighted ) { - dc->SetBrush( *m_owner->m_highlightBrush ); + dc->SetBrush( *m_owner->GetHighlightBrush() ); } else { @@ -1621,6 +1637,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 ); } } @@ -1650,27 +1668,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; + + xOld += ix; + width -= ix; + } - wxDCClipper clipper(*dc, x, y, width, rect.height); + 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(); } } @@ -1844,9 +1864,11 @@ void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) 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(); + wxDCClipper clipper(dc, x, HEADER_OFFSET_Y, cw-5, h-4 ); + + dc.DrawText( item.GetText(), + x + EXTRA_WIDTH, HEADER_OFFSET_Y + EXTRA_HEIGHT ); + x += wCol; if (xEnd > w+5) @@ -2162,7 +2184,8 @@ wxListMainWindow::wxListMainWindow() { Init(); - m_highlightBrush = (wxBrush *) NULL; + m_highlightBrush = + m_highlightUnfocusedBrush = (wxBrush *) NULL; m_xScroll = m_yScroll = 0; @@ -2179,7 +2202,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; @@ -2194,6 +2234,7 @@ wxListMainWindow::~wxListMainWindow() DoDeleteAllItems(); delete m_highlightBrush; + delete m_highlightUnfocusedBrush; delete m_renameTimer; } @@ -2401,7 +2442,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); } @@ -2417,11 +2458,14 @@ bool wxListMainWindow::HighlightLine( size_t line, bool highlight ) void wxListMainWindow::RefreshLine( size_t line ) { - size_t visibleFrom, visibleTo; - GetVisibleLinesRange(&visibleFrom, &visibleTo); + if ( HasFlag(wxLC_REPORT) ) + { + size_t visibleFrom, visibleTo; + GetVisibleLinesRange(&visibleFrom, &visibleTo); - if ( line < visibleFrom || line > visibleTo ) - return; + if ( line < visibleFrom || line > visibleTo ) + return; + } wxRect rect = GetLineRect(line); @@ -2494,6 +2538,37 @@ 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; + } + + 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); + } + } +} + void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) { // Note: a wxPaintDC must be constructed even if no drawing is @@ -2557,7 +2632,7 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) GetLine(line)->DrawInReportMode( &dc, rectLine, GetLineHighlightRect(line), - m_hasFocus && IsHighlighted(line) ); + IsHighlighted(line) ); } if ( HasFlag(wxLC_HRULES) ) @@ -2617,10 +2692,13 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) if ( HasCurrent() ) { // don't draw rect outline under Max if we already have the background - // color + // 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__ if ( !m_hasFocus ) -#endif // !__WXMAC__ +#else // !__WXMAC__ + if ( m_hasFocus ) +#endif // __WXMAC__/!__WXMAC__ { dc.SetPen( *wxBLACK_PEN ); dc.SetBrush( *wxTRANSPARENT_BRUSH ); @@ -3172,11 +3250,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: @@ -3208,12 +3291,11 @@ void wxListMainWindow::OnSetFocus( wxFocusEvent &WXUNUSED(event) ) { m_hasFocus = TRUE; - if ( HasCurrent() ) - RefreshLine( m_current ); - if (!GetParent()) return; + RefreshSelected(); + #ifdef __WXGTK__ g_focusWindow = GetParent(); #endif @@ -3227,8 +3309,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 ) @@ -3497,8 +3578,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 ) @@ -3510,9 +3592,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); } @@ -3526,10 +3612,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; @@ -3790,7 +3879,7 @@ void wxListMainWindow::RefreshAll() Refresh(); wxListHeaderWindow *headerWin = GetListCtrl()->m_headerWin; - if ( headerWin ) + if ( headerWin && headerWin->m_dirty ) { headerWin->m_dirty = FALSE; headerWin->Refresh(); @@ -3890,6 +3979,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 ); @@ -3968,8 +4058,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 */); }