diff --git a/docs/changes.txt b/docs/changes.txt index 1ca467f0b9..28a64dbd63 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -375,6 +375,7 @@ wxMSW: - Fix link error with wxSimplebook in DLL builds (Mark Roszko, #22805). - Avoid errors when including wx/msw/msvcrt.h before other wx headers (#23194). - Fix drawing owner-drawn menu items with bitmaps (Jacob Gillespie, #23230). +- Improve ScrollTo() with wxDV_VARIABLE_LINE_HEIGHT (Jens Göpfert, #23102). wxOSX: diff --git a/samples/dataview/dataview.cpp b/samples/dataview/dataview.cpp index 4b2f1d933e..0b76a5c1d3 100644 --- a/samples/dataview/dataview.cpp +++ b/samples/dataview/dataview.cpp @@ -103,6 +103,7 @@ private: void OnShowCurrent(wxCommandEvent& event); void OnSetNinthCurrent(wxCommandEvent& event); void OnChangeNinthTitle(wxCommandEvent& event); + void OnEnsureNinthAndSecondColumn(wxCommandEvent& event); void OnPrependList(wxCommandEvent& event); void OnDeleteList(wxCommandEvent& event); @@ -450,6 +451,7 @@ enum ID_SHOW_CURRENT, ID_SET_NINTH_CURRENT, ID_CHANGE_NINTH_TITLE, + ID_ENSURE_NINTH_SECOND_COLUMN, ID_PREPEND_LIST = 200, ID_DELETE_LIST = 201, @@ -503,6 +505,7 @@ wxBEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_BUTTON( ID_SHOW_CURRENT, MyFrame::OnShowCurrent ) EVT_BUTTON( ID_SET_NINTH_CURRENT, MyFrame::OnSetNinthCurrent ) EVT_BUTTON( ID_CHANGE_NINTH_TITLE, MyFrame::OnChangeNinthTitle ) + EVT_BUTTON( ID_ENSURE_NINTH_SECOND_COLUMN, MyFrame::OnEnsureNinthAndSecondColumn ) EVT_BUTTON( ID_PREPEND_LIST, MyFrame::OnPrependList ) EVT_BUTTON( ID_DELETE_LIST, MyFrame::OnDeleteList ) @@ -737,8 +740,15 @@ MyFrame::MyFrame(wxFrame *frame, const wxString &title, int x, int y, int w, int BuildDataViewCtrl(fifthPanel, Page_VarHeight); + wxBoxSizer* button_sizer5 = new wxBoxSizer(wxHORIZONTAL); + button_sizer5->Add( + new wxButton(fifthPanel, ID_ENSURE_NINTH_SECOND_COLUMN, + "Make ninth symphony and second column visible"), + wxSizerFlags().DoubleBorder()); + wxSizer *fifthPanelSz = new wxBoxSizer(wxVERTICAL); fifthPanelSz->Add(m_ctrl[Page_VarHeight], 1, wxGROW | wxALL, 5); + fifthPanelSz->Add(button_sizer5); fifthPanel->SetSizerAndFit(fifthPanelSz); // page showing the indexed list model @@ -1562,6 +1572,14 @@ void MyFrame::OnChangeNinthTitle(wxCommandEvent& WXUNUSED(event)) m_music_model->ItemChanged(item); } +void MyFrame::OnEnsureNinthAndSecondColumn(wxCommandEvent& WXUNUSED(event)) +{ + wxDataViewItem item(m_long_music_model->GetNinthItem()); + m_ctrl[Page_VarHeight]->Select(item); + wxDataViewColumn *col = m_ctrl[Page_VarHeight]->GetColumn(1); + m_ctrl[Page_VarHeight]->EnsureVisible(item, col); +} + void MyFrame::OnValueChanged( wxDataViewEvent &event ) { wxString title = m_music_model->GetTitle( event.GetItem() ); diff --git a/src/generic/datavgen.cpp b/src/generic/datavgen.cpp index ce902605eb..c5bba24f6b 100644 --- a/src/generic/datavgen.cpp +++ b/src/generic/datavgen.cpp @@ -822,6 +822,11 @@ public: int GetCountPerPage() const; int GetEndOfLastCol() const; + + // Returns the position where the given column starts. + // The column must be valid. + int GetColumnStart(int column) const; + unsigned int GetFirstVisibleRow() const; wxDataViewItem GetTopItem() const; @@ -3471,33 +3476,7 @@ void wxDataViewMainWindow::ScrollTo( int rows, int column ) int sy = y ? GetLineStart( rows )/y : -1; int sx = -1; if( column != -1 && x ) - { - wxRect rect = GetClientRect(); - int colnum = 0; - int x_start, w = 0; - int xx, yy, xe; - m_owner->CalcUnscrolledPosition( rect.x, rect.y, &xx, &yy ); - for (x_start = 0; colnum < column; colnum++) - { - wxDataViewColumn *col = GetOwner()->GetColumnAt(colnum); - if (col->IsHidden()) - continue; // skip it! - - w = col->GetWidth(); - x_start += w; - } - - int x_end = x_start + w; - xe = xx + rect.width; - if( x_end > xe ) - { - sx = ( xx + x_end - xe )/x; - } - if( x_start < xx ) - { - sx = x_start/x; - } - } + sx = GetColumnStart(column) / x; m_owner->Scroll( sx, sy ); } @@ -3543,6 +3522,39 @@ int wxDataViewMainWindow::GetEndOfLastCol() const return width; } +int wxDataViewMainWindow::GetColumnStart(int column) const +{ + wxASSERT(column >= 0); + int sx = -1; + + wxRect rect = GetClientRect(); + int colnum = 0; + int x_start, w = 0; + int xx, yy, xe; + m_owner->CalcUnscrolledPosition(rect.x, rect.y, &xx, &yy); + for (x_start = 0; colnum < column; colnum++) + { + wxDataViewColumn* col = GetOwner()->GetColumnAt(colnum); + if (col->IsHidden()) + continue; // skip it! + + w = col->GetWidth(); + x_start += w; + } + + int x_end = x_start + w; + xe = xx + rect.width; + if (x_end > xe) + { + sx = (xx + x_end - xe); + } + if (x_start < xx) + { + sx = x_start; + } + return sx; +} + unsigned int wxDataViewMainWindow::GetFirstVisibleRow() const { int x = 0; @@ -6444,12 +6456,33 @@ void wxDataViewCtrl::EnsureVisibleRowCol( int row, int column ) int first = m_clientArea->GetFirstVisibleRow(); int last = m_clientArea->GetLastFullyVisibleRow(); - if( row < first ) + if( row <= first ) + { m_clientArea->ScrollTo( row, column ); + } else if( row > last ) - m_clientArea->ScrollTo( row - last + first, column ); - else - m_clientArea->ScrollTo( first, column ); + { + if ( !HasFlag(wxDV_VARIABLE_LINE_HEIGHT) ) + { + // Simple case as we can directly find the item to scroll to. + m_clientArea->ScrollTo(row - last + first, column); + } + else + { + // calculate scroll position based on last visible item + const int itemStart = m_clientArea->GetLineStart(row); + const int itemHeight = m_clientArea->GetLineHeight(row); + const int clientHeight = m_clientArea->GetSize().y; + int scrollX, scrollY; + GetScrollPixelsPerUnit(&scrollX, &scrollY); + int scrollPosY = + (itemStart + itemHeight - clientHeight + scrollY - 1) / scrollY; + int scrollPosX = -1; + if (column != -1 && scrollX) + scrollPosX = m_clientArea->GetColumnStart(column) / scrollX; + Scroll(scrollPosX, scrollPosY); + } + } } void wxDataViewCtrl::EnsureVisible( const wxDataViewItem & item, const wxDataViewColumn * column )