X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/61fef19b852d426f5b00b60de083539b9ba0f76c..987263fe1974dac46a38d6d623557ccf89a25992:/src/generic/listctrl.cpp diff --git a/src/generic/listctrl.cpp b/src/generic/listctrl.cpp index ac046f88fd..dc42f4b08a 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 @@ -103,8 +103,8 @@ 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; @@ -117,10 +117,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; @@ -275,6 +282,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] @@ -305,7 +324,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 @@ -616,6 +635,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; @@ -723,8 +743,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; @@ -752,9 +770,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 { @@ -1112,96 +1127,93 @@ void wxListLineData::CalculateSize( wxDC *dc, int spacing ) 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(); - - 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; - } + s = item->GetText(); - 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 ); + if (lh < SCROLL_UNIT_Y) + lh = SCROLL_UNIT_Y; + 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,9 +1225,7 @@ void wxListLineData::CalculateSize( wxDC *dc, int spacing ) } } -void wxListLineData::SetPosition( int x, int y, - int WXUNUSED(window_width), - int spacing ) +void wxListLineData::SetPosition( int x, int y, int spacing ) { wxListItemDataList::compatibility_iterator node = m_items.GetFirst(); wxCHECK_RET( node, _T("no subitems at all??") ); @@ -1445,20 +1455,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); } } @@ -2083,11 +2104,11 @@ void wxListTextCtrl::OnKillFocus( wxFocusEvent &event ) { // We must finish regardless of success, otherwise we'll get focus problems Finish(); - + if ( !AcceptChanges() ) m_owner->OnRenameCancelled( m_itemEdited ); } - + event.Skip(); } @@ -2138,29 +2159,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, @@ -2195,8 +2199,7 @@ wxListMainWindow::wxListMainWindow( wxWindow *parent, wxSize sz = size; sz.y = 25; - InitScrolling(); - SetScrollbars( m_xScroll, m_yScroll, 0, 0, 0, 0 ); + SetScrollbars( SCROLL_UNIT_X, SCROLL_UNIT_Y, 0, 0, 0, 0 ); SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOX ) ); } @@ -2835,19 +2838,22 @@ bool wxListMainWindow::OnRenameAccept(size_t itemEdit, const wxString& value) # pragma message disable initnotreach #endif -void wxListMainWindow::OnRenameCancelled(size_t itemEdit) +void wxListMainWindow::OnRenameCancelled(size_t WXUNUSED(itemEdit)) { // wxMSW seems not to notify the program about // cancelled label edits. return; + #if 0 + // above unconditional return cause warning about not reachable code + // let owner know that the edit was cancelled wxListEvent le( wxEVT_COMMAND_LIST_END_LABEL_EDIT, GetParent()->GetId() ); - + // These only exist for wxTreeCtrl, which should probably be changed // le.m_editCancelled = TRUE; // le.m_label = wxEmptyString; - + le.SetEventObject( GetParent() ); le.m_itemIndex = itemEdit; @@ -2857,6 +2863,7 @@ void wxListMainWindow::OnRenameCancelled(size_t itemEdit) data->GetItem( 0, le.m_item ); GetEventHandler()->ProcessEvent( le ); + #endif } #ifdef __VMS__ # pragma message enable initnotreach @@ -3047,8 +3054,8 @@ 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 ); + int view_x = SCROLL_UNIT_X*GetScrollPos( wxHORIZONTAL ); + int view_y = SCROLL_UNIT_Y*GetScrollPos( wxVERTICAL ); if ( HasFlag(wxLC_REPORT) ) { @@ -3057,16 +3064,16 @@ void wxListMainWindow::MoveToItem(size_t item) ResetVisibleLinesRange(); if (rect.y < view_y ) - Scroll( -1, rect.y/m_yScroll ); + Scroll( -1, rect.y/SCROLL_UNIT_Y ); 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+SCROLL_UNIT_Y)/SCROLL_UNIT_Y ); } 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 ); } } @@ -3773,11 +3780,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); @@ -3803,6 +3857,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; @@ -3833,104 +3889,170 @@ void wxListMainWindow::RecalculatePositions(bool noRefresh) if ( HasFlag(wxLC_REPORT) ) { - // all lines have the same height + // all lines have the same height and we scroll one line per step int lineHeight = GetLineHeight(); - // scroll one line per step - m_yScroll = lineHeight; - - size_t lineCount = GetItemCount(); - int entireHeight = lineCount*lineHeight + LINE_SPACING; + 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; - - 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; - } + int x = EXTRA_BORDER_X; + int y = EXTRA_BORDER_Y; - // 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); } + } + + + SetScrollbars + ( + SCROLL_UNIT_X, + SCROLL_UNIT_Y, + (x + SCROLL_UNIT_X) / SCROLL_UNIT_X, + (y + SCROLL_UNIT_Y) / SCROLL_UNIT_Y, + 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 - // We have reached the last item. - if ( i == count - 1 ) - entireWidth += maxWidth; + int entireWidth = 0; + #if 0 + // entireHeight is not used so no need to define it + int entireHeight = 0; + #endif - if ( (tries == 0) && (entireWidth+SCROLL_UNIT_X > clientWidth) ) + for (int tries = 0; tries < 2; tries++) + { + entireWidth = 2*EXTRA_BORDER_X; + #if 0 + // entireHeight is not used so no need to define it + entireHeight = 2*EXTRA_BORDER_Y; + #endif + + 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; + currentlyVisibleLines = 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, + SCROLL_UNIT_Y, + (entireWidth + SCROLL_UNIT_X) / SCROLL_UNIT_X, + 0, + GetScrollPos( wxHORIZONTAL ), + 0, + TRUE + ); + } } if ( !noRefresh ) @@ -4228,18 +4350,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") ); @@ -4253,6 +4396,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); @@ -4422,6 +4573,7 @@ wxGenericListCtrl::wxGenericListCtrl() m_mainWin = (wxListMainWindow*) NULL; m_headerWin = (wxListHeaderWindow*) NULL; + m_headerHeight = 0; } wxGenericListCtrl::~wxGenericListCtrl() @@ -4434,15 +4586,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 there is not enough space + 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, @@ -4665,11 +4840,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; } @@ -4699,6 +4879,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 ); @@ -5001,8 +5188,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 { @@ -5013,7 +5200,7 @@ void wxGenericListCtrl::ResizeReportView(bool showHeader) void wxGenericListCtrl::OnInternalIdle() { wxWindow::OnInternalIdle(); - + // do it only if needed if ( !m_mainWin->m_dirty ) return; @@ -5069,8 +5256,11 @@ bool wxGenericListCtrl::SetFont( const wxFont &font ) if (m_headerWin) { m_headerWin->SetFont( font ); + CalculateAndSetHeaderHeight(); } + Refresh(); + return TRUE; }